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

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

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

String variable = getSomeString();

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

function getSomeString {
   echo "tadaa"
}

VARIABLE=$(getSomeString)

当前回答

Bash模式返回标量和数组值对象:

定义

url_parse() { # parse 'url' into: 'url_host', 'url_port', ...
   local "$@" # inject caller 'url' argument in local scope
   local url_host="..." url_path="..." # calculate 'url_*' components
   declare -p ${!url_*} # return only 'url_*' object fields to the caller
}

调用

main() { # invoke url parser and inject 'url_*' results in local scope
   eval "$(url_parse url=http://host/path)" # parse 'url'
   echo "host=$url_host path=$url_path" # use 'url_*' components
}

其他回答

你可以让这个函数把一个变量作为第一个参数,然后用你想要返回的字符串修改变量。

#!/bin/bash
set -x
function pass_back_a_string() {
    eval "$1='foo bar rab oof'"
}

return_var=''
pass_back_a_string return_var
echo $return_var

打印“foo bar rab oof”。

编辑:在适当的地方添加引用,以允许字符串中的空白地址@Luca Borrione的评论。

编辑:作为演示,请参阅下面的程序。这是一种通用的解决方案:它甚至允许您将字符串接收到局部变量中。

#!/bin/bash
set -x
function pass_back_a_string() {
    eval "$1='foo bar rab oof'"
}

return_var=''
pass_back_a_string return_var
echo $return_var

function call_a_string_func() {
     local lvar=''
     pass_back_a_string lvar
     echo "lvar='$lvar' locally"
}

call_a_string_func
echo "lvar='$lvar' globally"

这个打印:

+ return_var=
+ pass_back_a_string return_var
+ eval 'return_var='\''foo bar rab oof'\'''
++ return_var='foo bar rab oof'
+ echo foo bar rab oof
foo bar rab oof
+ call_a_string_func
+ local lvar=
+ pass_back_a_string lvar
+ eval 'lvar='\''foo bar rab oof'\'''
++ lvar='foo bar rab oof'
+ echo 'lvar='\''foo bar rab oof'\'' locally'
lvar='foo bar rab oof' locally
+ echo 'lvar='\'''\'' globally'
lvar='' globally

编辑:演示原始变量的值在函数中可用,正如@Xichen Li在评论中错误地批评的那样。

#!/bin/bash
set -x
function pass_back_a_string() {
    eval "echo in pass_back_a_string, original $1 is \$$1"
    eval "$1='foo bar rab oof'"
}

return_var='original return_var'
pass_back_a_string return_var
echo $return_var

function call_a_string_func() {
     local lvar='original lvar'
     pass_back_a_string lvar
     echo "lvar='$lvar' locally"
}

call_a_string_func
echo "lvar='$lvar' globally"

输出如下:

+ return_var='original return_var'
+ pass_back_a_string return_var
+ eval 'echo in pass_back_a_string, original return_var is $return_var'
++ echo in pass_back_a_string, original return_var is original return_var
in pass_back_a_string, original return_var is original return_var
+ eval 'return_var='\''foo bar rab oof'\'''
++ return_var='foo bar rab oof'
+ echo foo bar rab oof
foo bar rab oof
+ call_a_string_func
+ local 'lvar=original lvar'
+ pass_back_a_string lvar
+ eval 'echo in pass_back_a_string, original lvar is $lvar'
++ echo in pass_back_a_string, original lvar is original lvar
in pass_back_a_string, original lvar is original lvar
+ eval 'lvar='\''foo bar rab oof'\'''
++ lvar='foo bar rab oof'
+ echo 'lvar='\''foo bar rab oof'\'' locally'
lvar='foo bar rab oof' locally
+ echo 'lvar='\'''\'' globally'
lvar='' globally

#实现一个通用的函数返回堆栈:

STACK=()
push() {
  STACK+=( "${1}" )
}
pop() {
  export $1="${STACK[${#STACK[@]}-1]}"
  unset 'STACK[${#STACK[@]}-1]';
}

#用法:

my_func() {
  push "Hello world!"
  push "Hello world2!"
}
my_func ; pop MESSAGE2 ; pop MESSAGE1
echo ${MESSAGE1} ${MESSAGE2}
agt@agtsoft:~/temp$ cat ./fc 
#!/bin/sh

fcall='function fcall { local res p=$1; shift; fname $*; eval "$p=$res"; }; fcall'

function f1 {
    res=$[($1+$2)*2];
}

function f2 {
    local a;
    eval ${fcall//fname/f1} a 2 3;
    echo f2:$a;
}

a=3;
f2;
echo after:a=$a, res=$res

agt@agtsoft:~/temp$ ./fc
f2:10
after:a=3, res=

为了说明我对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]"

不过还是很恶心。

Bash模式返回标量和数组值对象:

定义

url_parse() { # parse 'url' into: 'url_host', 'url_port', ...
   local "$@" # inject caller 'url' argument in local scope
   local url_host="..." url_path="..." # calculate 'url_*' components
   declare -p ${!url_*} # return only 'url_*' object fields to the caller
}

调用

main() { # invoke url parser and inject 'url_*' results in local scope
   eval "$(url_parse url=http://host/path)" # parse 'url'
   echo "host=$url_host path=$url_path" # use 'url_*' components
}