不同shell脚本解释器中函数的本地变量

时间:2017-02-09 09:58:54

标签: bash shell

我正在尝试提高脚本的可移植性,因此它可以在各种解释器中运行(唉,每个解释器都有自己的标准和代数)。目前,测试套件尝试在Debian中提供的bashdash / ashzshbusybox shksh中运行相同的代码适用于Solaris / illumos的Linux和bashzshksh88ksh93

虽然大多数构造都可以被驱动到最低公分母(我甚至可以使用它,例如shell regexp支持,如果可用或者回退到外部grep / sed / {{1}在我需要它工作的地方),有一个特殊的打嗝,递归调用函数 - 以及每个层想要保持局部值的变量。不幸的是,方程式中至少有一些KSH解释器根本不支持awk关键字,它们的等价物是localtypeset varname,甚至可能需要typeset var varname。我确实设法根据检测到的shell解释器typeset varname=initialValue来解决这个问题,大致如下:

eval

在此脚本的输出中,应该看到“outside”值打印# there is really a bit more magic to try and detect a shell interpreter if [ -z "${LOCALKEYWORD-}" ]; then LOCALKEYWORD="typeset var" [ -n "${BASH-}" ] && LOCALKEYWORD="local" fi x=4 y=5 test() { eval $LOCALKEYWORD x y=$(expr $y + 1) x=$(expr $x + 1) echo "INSIDE: $x $y" } echo "OUTSIDE: $x $y" test echo "OUTSIDE: $x $y" test echo "OUTSIDE: $x $y" ,而“inside”值为4 (y+1),因为1 (y+1)用locality重新初始化(开始为空,然后是<{1}}数学将其设置为x)而expr是继承的。

在这种情况下,1也会继承来电者的y值,因此它会为“内部”报告提供busybox sh,我想这可以说是合理的(所以一个必须将局部变量初始化为可预测的值,没问题。)

不幸的是,我发现KSH地区仅适用于“真实”函数声明,拼写为x - 使用5 (y+1)关键字,名称后面没有function name { ... ; }个括号。但是,此语法中的某些shell(function())barf并且不接受busybox sh作为有效关键字:

dash

所以我试着进一步包装它:

function

这令人惊讶地起作用......差不多。

function test2 {
    echo YES
}

./local.sh: line 19: function: not found
YES
./local.sh: line 21: syntax error: unexpected "}"

Bash对这两种语法都没有问题(可以同时执行KSH #!/bin/sh if [ -z "${LOCALKEYWORD-}" ]; then LOCALKEYWORD="typeset var" #LOCALKEYWORD="declare" [ -n "${BASH-}" ] && LOCALKEYWORD=local fi x=4 y=5 test_att() { eval $LOCALKEYWORD x y=$(expr $y + 1) x=$(expr $x + 1) echo "INSIDE: $x $y" } if [ "$LOCALKEYWORD" != local ]; then test() { function test_ksh { test_att "$@"; } test_ksh "$@" } else test() { test_att "$@"; } fi echo "OUTSIDE: $x $y" test echo "OUTSIDE: $x $y" test echo "OUTSIDE: $x $y" 和AT&amp; T for SHELL_PROG in bash dash zsh "busybox sh" ksh ; do for LOCALKEYWORD in "typeset var" "typeset" "local"; do echo "=== $SHELL_PROG with $LOCALKEYWORD" (export LOCALKEYWORD; $SHELL_PROG ./local.sh) echo "" done echo "" done 以及function name {}name() {});对于这个例子,typeset似乎同样是杂食性的,都产生了

local

对于这三种情况中的每一种。

zsh适用于OUTSIDE: 4 5 INSIDE: 1 6 OUTSIDE: 4 6 INSIDE: 1 7 OUTSIDE: 4 7 变体和ksh的中断,正如预期的那样开始冒险。

不幸的是,typesetlocal仍拒绝解析busybox sh ed-away例程:

dash

如果我评论if行,则./local.sh: 23: ./local.sh: Syntax error: "}" unexpected (expecting "fi") 代码路径的变体会失败(因此KSH支持会丢失),但function test_ksh { test_att "$@"; }typeset都会开始工作(继承调用者的busybox sh值,因此它应该在函数中初始化,但调用者的值不会按预期的每个请求的位置替换。)

我希望有人能帮助我解决后一个问题,并且可以随意使用上述技巧。我真的很惊讶我至少得到了这么远;)

吉姆

0 个答案:

没有答案