sh 外壳下的数组(不是 bash)



一个简单的问题,我可以在sh下使用数组,而不是bashzsh或其他任何东西。

ARRAYNAME=(value1 value2 .... valueN)
上面的命令仅适用于bashsh还有其他选择吗?
我试图搜索这样的问题,但没有找到纯sh的答案。

POSIX sh 中每个堆栈帧只有一个"数组",那就是当前范围的参数列表。

您可以重置它:

set -- "first item" "second item"

。附加到它:

set -- "$@" "new item"

。从前面删除内容:

echo "First item is $1"
shift
echo "First item is $1"

。并通过跳转到新的函数作用域来创建一个新的函数:

someFunc() {
echo "The argument list for this function is:" >&2
printf ' - %sn' "$@"
}
someFunc argOne argTwo

。但是因为一次只有一个范围,所以它非常有限。

如果没有限制,ksh(以及后来bash 和其他人)就没有理由添加任何其他形式的数组!


一种技巧是滥用字符串,就好像它们是数组一样,当您需要索引它们时将它们拆分为函数参数:

s='A|B|C|D' # specify your "array" as a string with a sigil between elements
IFS='|'     # specify separator between elements
set -f      # disable glob expansion, so a * doesn't get replaced with a list of files
getNth()  { shift "$(( $1 + 1 ))"; printf '%sn' "$1"; }
getLast() { getNth "$(( $(length "$@") - 1 ))" "$@"; }
length()  { echo "$#"; }
length $s   # emits 4
getNth 0 $s # emits A
getNth 1 $s # emits B
getLast $s  # emits D

当然,这意味着您需要保留值中不存在的符号字符。


作为一个与上述类似操作的第三方 shell 库(将"数组"编码为字符串,并在这些字符串中存储和检索内容),但具有转义/取消转义支持,因此不需要符号,您也可以看看 https://github.com/makefu/array/blob/master/array。也就是说,上面的代码为每次查找调用外部可执行文件 - 通过使用 POSIX sh 为每个操作调用sedawk副本的额外运行时开销,您将很快失去在 shell 启动时间中获得的任何收益。

最新更新