Sub*_*isM 39 shell array bourne-shell
我正在尝试在 Bourne shell ( /bin/sh) 中使用数组。我发现初始化数组元素的方法是:
arr=(1 2 3)
Run Code Online (Sandbox Code Playgroud)
但它遇到了一个错误:
syntax error at line 8: `arr=' unexpected
Run Code Online (Sandbox Code Playgroud)
现在,我发现此语法的帖子说它是 for bash,但我找不到 Bourne shell 的任何单独语法。语法是否/bin/sh也一样?
Sté*_*las 61
/bin/sh现在几乎不是任何系统上的 Bourne shell(即使是 Solaris,它是最后一个包含它的主要系统之一,现在它在 Solaris 11 中的 /bin/sh 已切换到 POSIX sh)。/bin/sh是 70 年代初的汤普森外壳。1979 年,Bourne shell 在 Unix V7 中取代了它。
/bin/sh 此后多年一直是 Bourne shell(或 Almquist shell,BSD 上的免费重新实现)。
如今,/bin/sh更常见的是 POSIXsh语言的解释器或另一个解释器,它本身基于 ksh88 语言的子集(以及具有一些不兼容性的 Bourne shell 语言的超集)。
Bourne shell 或 POSIX sh 语言规范不支持数组。或者更确切地说,它们只有一个数组:位置参数($1, $2, $@,因此每个函数也有一个数组)。
ksh88 确实有您使用 设置的数组set -A,但是没有在 POSIX sh 中指定,因为语法很笨拙且不太实用。
其他带有数组/列表变量的 shell 包括:csh/ tcsh、rc、es、bash(主要以 ksh93 方式复制 ksh 语法)、yash、zsh,fish每个都有不同的语法(rc曾经是 Unix 的后继者的 shell,fish并且zsh是最一致的那些)...
在标准中sh(也适用于 Bourne shell 的现代版本):
set '1st element' 2 3 # setting the array
set -- "$@" more # adding elements to the end of the array
shift 2 # removing elements (here 2) from the beginning of the array
printf '<%s>\n' "$@" # passing all the elements of the $@ array
# as arguments to a command
for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"\n' "$i"
done
printf '%s\n' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "${10}") past the 9th in other
# shells (except zsh, when not in sh emulation and
# most ash-based shells).
printf '%s\n' "$# elements in the array"
printf '%s\n' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)
Run Code Online (Sandbox Code Playgroud)
(注意,在 Bourne shell 和 ksh88 中,$IFS必须包含空格字符"$@"才能正常工作(一个错误),而在 Bourne shell 中,您无法访问上面的元素$9(${10}不起作用,您仍然可以执行shift 1; echo "$9"或循环他们))。
正如其他人所说,Bourne Shell 没有真正的数组。
但是,根据您需要执行的操作,分隔字符串就足够了:
sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%s\n' "$word"
done
Run Code Online (Sandbox Code Playgroud)
如果典型的分隔符(空格、制表符和换行符)不够用,您可以IFS在循环之前设置为您想要的任何分隔符。
如果您需要以编程方式构建数组,则只需构建一个分隔字符串即可。
普通 Bourne shell 中没有数组。可以使用以下方式创建数组并遍历它:
#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell
array_traverse()
{
for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo \$$current_value)
done
return 1
}
ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3
Run Code Online (Sandbox Code Playgroud)
无论sh你选择哪种方式使用数组,它总是很麻烦。如果可以的话,请考虑使用不同的语言,例如Python或Perl,除非您受限于非常有限的平台或想要学习一些东西。