我需要将脚本中的命令输出读入数组。 该命令是例如:
ps aux | grep | grep | x
并且这样一行一行地输出输出;
10 20 30
我需要从命令输出读取数组的值,然后我会做一些工作,如果数组的大小<3。
您可以使用
my_array=( $(<command>) )
将命令<command>
的输出存储到数组my_array
。
您可以使用该数组的长度
my_array_length=${#my_array[@]}
现在长度存储在my_array_length
。
如果命令的输出包含空格(相当频繁)或像*
,?这样的水平字符,则其他答案将会中断?
, [...]
。
要获得数组中的命令的输出,基本上有两种方法:
Bash≥4使用mapfile
– 这是最有效的:
mapfile -t my_array < <( my_command )
否则,读取输出的循环(较慢,但安全):
my_array=() while IFS= read -r line; do my_array+=( "$line" ) done < <( my_command )
你可能会看到很多这样的:
my_array=( $( my_command) )
但是不要使用它! 看看它是如何被打破的:
$ # this is the command used to test: $ echo "one two"; echo "three four" one two three four $ my_array=( $( echo "one two"; echo "three four" ) ) $ declare -p my_array declare -a my_array='([0]="one" [1]="two" [2]="three" [3]="four")' $ # Not good! now look: $ mapfile -t my_array < <(echo "one two"; echo "three four") $ declare -p my_array declare -a my_array='([0]="one two" [1]="three four")' $ # Good!
然后有人会推荐使用IFS=$'\n'
来解决这个问题:
$ IFS=$'\n' $ my_array=( $(echo "one two"; echo "three four") ) $ declare -p my_array declare -a my_array='([0]="one" [1]="two" [2]="three" [3]="four")' $ # It works!
但现在让我们使用另一个命令:
$ echo "* one two"; echo "[three four]" * one two [three four] $ IFS=$'\n' $ my_array=( $(echo "* one two"; echo "[three four]") ) $ declare -p my_array declare -a my_array='([0]="* one two" [1]="t")' $ # What?
这是因为我在当前目录中有一个名为t
的文件,而且这个文件名与glob [three four]
匹配…在这一点上,有些人会建议使用set -f
来禁用globbing:但是看看它:你必须改变IFS
和使用set -f
能够修复一个破碎的技术(你甚至没有修复它真的)! 当我们这样做的时候,我们真的是在对抗外壳,而不是在外壳上工作 。
$ mapfile -t my_array < <( echo "* one two"; echo "[three four]") $ declare -p my_array declare -a my_array='([0]="* one two" [1]="[three four]")'
这里我们正在使用shell!
想象一下,你打算把文件和目录名称(在当前文件夹下)放到一个数组中并计数它的项目。 剧本会是这样的;
my_array=( `ls` ) my_array_length=${#my_array[@]} echo $my_array_length
或者,您可以通过添加以下脚本来遍历此数组:
for element in "${my_array[@]}" do echo "${element}" done