• 86499

    文章

  • 757

    评论

  • 18

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

如何从Bash函数返回字符串值

撸了今年阿里、腾讯和美团的面试,我有一个重要发现.......>>

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

我将用Java编写示例以显示我想做的事情:

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

String variable = getSomeString();

下面的示例在bash中有效,但是有更好的方法吗?

function getSomeString {
   echo "tadaa"
}

VARIABLE=$(getSomeString)

#1楼

考虑以下代码,向Vicky Ronnen抬起头来:

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正确指出的那样。


#2楼

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=

#3楼

像上面的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时,速度差异似乎更为明显,因为从函数调用捕获stdout几乎是灾难性的。

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

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

#4楼

正如其他人所写,最直接,最可靠的解决方案是使用命令替换:

assign()
{
    local x
    x="Test"
    echo "$x"
}

x=$(assign) # This assigns string "Test" to x

缺点是性能,因为这需要单独的过程。

本主题中建议的另一种技术,即传递要分配给变量的变量名称作为参数,会产生副作用,我不建议以其基本形式使用它。 问题是您可能需要在函数中使用一些变量来计算返回值,并且可能会发生的是,用于存储返回值的变量名称会干扰其中之一:

assign()
{
    local x
    x="Test"
    eval "$1=\$x"
}

assign y # This assigns string "Test" to y, as expected

assign x # This will NOT assign anything to x in this scope
         # because the name "x" is declared as local inside the function

当然,您可能不将函数的内部变量声明为局部变量,但实际上应始终这样做,否则,如果存在一个同名变量,则您可能会意外覆盖父作用域中不相关的变量。

一种可能的解决方法是将传递的变量显式声明为global:

assign()
{
    local x
    eval declare -g $1
    x="Test"
    eval "$1=\$x"
}

如果将名称“ x”作为参数传递,则函数主体的第二行将覆盖先前的本地声明。 但是名称本身可能仍然会干扰,因此,如果您打算使用先前存储在传递的变量中的值,然后再在其中写入返回值,请注意,您必须从一开始就将其复制到另一个局部变量中。 否则结果将不可预测! 此外,这仅适用于最新的BASH版本4.2。 更多可移植的代码可能会使用具有相同效果的显式条件构造:

assign()
{
    if [[ $1 != x ]]; then
      local x
    fi
    x="Test"
    eval "$1=\$x"
}

也许最优雅的解决方案只是为函数返回值保留一个全局名称,并在您编写的每个函数中一致地使用它。


#5楼

如前所述,从函数返回字符串的“正确”方法是使用命令替换。 如果该函数也需要输出到控制台(如@Mani所述),请在该函数的开头创建一个临时fd并重定向到控制台。 返回字符串之前,请关闭临时fd。

#!/bin/bash
# file:  func_return_test.sh
returnString() {
    exec 3>&1 >/dev/tty
    local s=$1
    s=${s:="some default string"}
    echo "writing directly to console"
    exec 3>&-     
    echo "$s"
}

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

执行没有参数的脚本会产生...

# ./func_return_test.sh
writing directly to console
my_string:  [some default string]

希望这可以帮助人们

-安迪


695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网站提供最新的站长新闻,各种互联网资讯。 还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿大家一起进步!

转载原创文章请注明出处,转载至: 梁钟霖个人博客www.liangzl.com

0条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤
注册梁钟霖个人博客