在Bash中将命令的输出读入数组

我需要将脚本中的命令输出读入数组。 该命令是例如:

ps aux | grep | grep | x 

并且这样一行一行地输出输出;

 10 20 30 

我需要从命令输出读取数组的值,然后我会做一些工作,如果数组的大小<3。

您可以使用

 my_array=( $(<command>) ) 

将命令<command>的输出存储到数组my_array

您可以使用该数组的长度

 my_array_length=${#my_array[@]} 

现在长度存储在my_array_length

如果命令的输出包含空格(相当频繁)或像* ,?这样的水平字符,则其他答案将会中断?[...]

要获得数组中的命令的输出,基本上有两种方法:

  1. Bash≥4使用mapfile – 这是最有效的:

     mapfile -t my_array < <( my_command ) 
  2. 否则,读取输出的循环(较慢,但安全):

     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