我想从Bash函数返回一个字符串。

我将用java写这个例子来说明我想做什么:

public String getSomeString() {
  return "tadaa";
}

String variable = getSomeString();

下面的示例可以在bash中工作,但是是否有更好的方法来做到这一点?

function getSomeString {
   echo "tadaa"
}

VARIABLE=$(getSomeString)

当前回答

像上面的bstpierre一样,我使用并推荐使用显式命名输出变量:

function some_func() # OUTVAR ARG1
{
   local _outvar=$1
   local _result # Use some naming convention to avoid OUTVARs to clash
   ... some processing ....
   eval $_outvar=\$_result # Instead of just =$_result
}

注意引用$的用法。这将避免将$result中的内容解释为shell特殊字符。我发现这比result=$(some_func "arg1")捕获回声的习惯用法快一个数量级。在MSYS上使用bash时,速度差异似乎更加显著,从函数调用中捕获标准输出几乎是灾难性的。

可以发送一个局部变量,因为局部变量在bash中是动态作用域的:

function another_func() # ARG
{
   local result
   some_func result "$1"
   echo result is $result
}

其他回答

为了说明我对Andy的回答的评论,使用额外的文件描述符操作来避免使用/dev/tty:

#!/bin/bash

exec 3>&1

returnString() {
    exec 4>&1 >&3
    local s=$1
    s=${s:="some default string"}
    echo "writing to stdout"
    echo "writing to stderr" >&2
    exec >&4-
    echo "$s"
}

my_string=$(returnString "$*")
echo "my_string:  [$my_string]"

不过还是很恶心。

在我的程序中,按照约定,这就是预先存在的$REPLY变量的用途,read正是为此目的而使用它。

function getSomeString {
  REPLY="tadaa"
}

getSomeString
echo $REPLY

这种回声

tadaa

但是为了避免冲突,任何其他全局变量都可以。

declare result

function getSomeString {
  result="tadaa"
}

getSomeString
echo $result

如果这还不够,我推荐Markarian451的解决方案。

你拥有它的方式是在不破坏范围的情况下做到这一点的唯一方法。Bash没有返回类型的概念,只有退出码和文件描述符(stdin/out/err等)。

提醒薇姬·罗嫩,考虑一下下面的代码

function use_global
{
    eval "$1='changed using a global var'"
}

function capture_output
{
    echo "always changed"
}

function test_inside_a_func
{
    local _myvar='local starting value'
    echo "3. $_myvar"

    use_global '_myvar'
    echo "4. $_myvar"

    _myvar=$( capture_output )
    echo "5. $_myvar"
}

function only_difference
{
    local _myvar='local starting value'
    echo "7. $_myvar"

    local use_global '_myvar'
    echo "8. $_myvar"

    local _myvar=$( capture_output )
    echo "9. $_myvar"
}

declare myvar='global starting value'
echo "0. $myvar"

use_global 'myvar'
echo "1. $myvar"

myvar=$( capture_output )
echo "2. $myvar"

test_inside_a_func
echo "6. $_myvar" # this was local inside the above function

only_difference

将会给

0. global starting value
1. changed using a global var
2. always changed
3. local starting value
4. changed using a global var
5. always changed
6. 
7. local starting value
8. local starting value
9. always changed

也许正常的场景是使用test_inside_a_func函数中使用的语法,因此在大多数情况下可以同时使用这两种方法,尽管捕获输出是在任何情况下都能工作的更安全的方法,它模仿在其他语言中可以找到的函数的返回值,Vicky Ronnen正确地指出了这一点。

没有比这更好的方法了。Bash只知道写入标准输出的状态码(整数)和字符串。