sh shell下的数组(不是bash)

Asy*_*ode 1 linux shell

一个简单的问题,我可以在just sh,not bash zsh或any else 下使用数组.

ARRAYNAME=(value1 value2 .... valueN)
上面的命令只适用于bash.是否有任何替代sh
我试图搜索这样的问题,但没有找到纯粹的答案.

Cha*_*ffy 5

POSIX sh中每个堆栈帧只有一个"数组",这是当前作用域的参数列表.

你可以重置它:

set -- "first item" "second item"
Run Code Online (Sandbox Code Playgroud)

...附加到它:

set -- "$@" "new item"
Run Code Online (Sandbox Code Playgroud)

......从前面移除东西:

echo "First item is $1"
shift
echo "First item is $1"
Run Code Online (Sandbox Code Playgroud)

...并通过跳转到新的函数范围来创建一个新的:

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

someFunc argOne argTwo
Run Code Online (Sandbox Code Playgroud)

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

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


一个hack是滥用字符串就像它们是数组一样,当你需要索引它们时将它们分成函数参数:

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 '%s\n' "$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
Run Code Online (Sandbox Code Playgroud)

当然,这意味着您需要具有值中不存在的保留的sigil字符.


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