我们如何在 Unix shell 脚本中将命令的输出存储为数组?

我们如何在 Unix shell 脚本中将命令的输出存储为数组?

我想将命令的输出存储到数组中。我尝试使用以下命令,该命令是从此处提出的类似问题中得到的。请在下面找到我使用的 shell 命令:

#!/bin/ksh

mailx -H >mytest.txt
#awk '/Incident/{ print NR;}' mytest.txt >lineNum.txt
msgNumbers=$(awk '/Incident/{ print NR;}' mytest.txt)
echo $msgNumbers

我可以在 UNIX 中直接执行此命令得到所需的结果。但是当我在 shell 脚本中使用相同的命令时,出现错误:

"syntax error at line 5: `msgNumbers=$' unexpected"

有人可以指出其中的错误吗?

答案1

如果您使用 Bourne shell 解释该脚本,就会出现这个错误,Bourne shell 是一种 70 年代非常古老的 shell,如今几乎不再使用,除非在 Solaris 10 及更早版本上。

所以我敢打赌,该脚本是/bin/sh在 Solaris 10 或更早版本上解释的,而不是ksh.在 Solaris 上,标准sh采用/usr/xpg4/bin/sh.

Bourne shell 不支持$(...)命令替换的形式,您必须使用命令`...`替换。

无论如何,Bourne shell 和 POSIXsh规范都不支持数组。要将 Solaris 10 /bin/ksh(基于 ksh88)命令输出的非空行内容分配给数组变量,您需要:

set -o noglob
IFS='
'
set -A array -- $(cmd)

(请注意,ksh88 数组的元素不能超过 4096 个)。

然后将数组的元素显示为:

((${#array[@]})) && printf '"%s"\n' "${array[@]}"

如果您的脚本有#!/bin/kshshe-bang,则应将其调用为/path/to/the/scriptor ksh /path/to/the/script,而不是sh /path/to/the/script

答案2

要将命令输出的单独单词分配给 中的数组ksh,您可以这样做

array=( $( mycommand ) )

这将运行mycommand(在您的情况下是该awk命令),并且该命令的输出将被拆分为空格上的单词(默认情况下是空格、制表符和换行符,这是IFSshell 变量的内容)。然后 shell 还会对每个单词执行文件名生成(“globbing”),除非set -f有效。

要输出这些元素,您可以使用

printf 'Element: %s\n' "${array[@]}"

或者

printf 'Elements: %s\n' "${array[*]}"

取决于您是想单独输出每个元素(第一个选项),还是一起输出每个元素,并用第一个字符分隔IFS(第二个选项)。这样做echo $array只会输出数组的第一个元素(而且,由于它没有被引用,因此将其分割为空格并执行文件名生成)。

或者,您可以只运行awk命令,而无需尝试将输出存储在任何地方(因为这显然也会输出结果)。这取决于您想要对awk命令结果执行的操作。

相关内容