我正在尝试提高脚本的可移植性,因此它可以在各种解释器中运行(唉,每个解释器都有自己的标准和代数)。目前,测试套件尝试在Debian中提供的bash
,dash
/ ash
,zsh
,busybox sh
,ksh
中运行相同的代码适用于Solaris / illumos的Linux和bash
,zsh
,ksh88
和ksh93
。
虽然大多数构造都可以被驱动到最低公分母(我甚至可以使用它,例如shell regexp支持,如果可用或者回退到外部grep
/ sed
/ {{1}在我需要它工作的地方),有一个特殊的打嗝,递归调用函数 - 以及每个层想要保持局部值的变量。不幸的是,方程式中至少有一些KSH解释器根本不支持awk
关键字,它们的等价物是local
或typeset 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
的中断,正如预期的那样开始冒险。
不幸的是,typeset
和local
仍拒绝解析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
值,因此它应该在函数中初始化,但调用者的值不会按预期的每个请求的位置替换。)
我希望有人能帮助我解决后一个问题,并且可以随意使用上述技巧。我真的很惊讶我至少得到了这么远;)
吉姆