如何在 POSIX shell 脚本中使用伪数组?
我想将 Bash 脚本中包含 10 个整数的数组替换为某物与 POSIX shell 脚本类似。
我设法遇到了Rich 的 sh (POSIX shell) 技巧,在截面上使用数组。
我尝试过的:
save_pseudo_array()
{
for i do
printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
done
echo " "
}
coords=$(save_pseudo_array "$@")
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
eval "set -- $coords"
我不明白,这就是问题所在,如果有人能解释一下,非常感谢。
答案1
基本思想是用来set
重新创建使用数组中的索引值的体验。因此,当您想要使用数组时,您可以set
使用值来运行;那是
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
然后您可以使用$1
、$2
等for
来处理给定的值。
如果您需要多个数组,那么所有这些都没有多大用处。这就是save
andeval
技巧的用武之地:里奇save
函数1 处理当前位置参数并输出一个带有适当引用的字符串,然后可以使用该字符串来eval
恢复存储的值。这样你就跑了
coords=$(save "$@")
将当前工作数组保存到 中coords
,然后创建一个新数组,使用它,当您需要再次使用时coords
,您eval
可以:
eval "set -- $coords"
要理解这个示例,您必须考虑到您正在使用两个数组,一个是之前设置的值,您将其存储在 中coords
,另一个数组包含 1895、955 等。代码片段本身并没有那么重要。就其本身而言,您需要在set
和eval
行之间进行一些处理。如果稍后需要返回 1895, 955 数组,请在恢复之前先保存该数组coords
:
newarray=$(save "$@")
eval "set -- $coords"
这样您就可以$newarray
稍后恢复。
1 定义为
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
答案2
这个想法是将任意字符串列表编码为标量变量,其格式稍后可用于重建列表或任意字符串。
$ save_pseudo_array x "y z" $'x\ny' "a'b"
'x' \
'y z' \
'x
y' \
'a'\''b' \
$
当你坚持set --
在前面时,它会生成 shell 代码来重建x
,y z
字符串列表并将其存储在$@
数组中,你只需要eval
使用它即可。
负责sed
正确引用每个字符串('
在第一行的开头、最后一行的末尾添加并用 替换所有'
s '\''
)。
然而,这意味着为每个参数运行一个printf
命令sed
,因此效率相当低。这可以通过一种更直接的方式完成,只需调用一次 awk:
save_pseudo_array() {
LC_ALL=C awk -v q=\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q "\\" q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
}' "$@"
}