在Bash中读取命令的输出到数组中。

时间:2021-03-24 15:42:54

I need to read the output of the command in my script into an array. The command is for example:

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

ps aux | grep | grep | x 

and it gives the output line by line like this;

它的输出线是这样的;

10
20
30

I need to read the values from the command output to array and then I will do some work if the size of array<3.

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

3 个解决方案

#1


53  

You can use

您可以使用

my_array=( $(<command>) )

to store the output of command <command> into the array my_array.

将命令的输出存储到数组my_array中。

You can access the length of that array using

您可以使用

my_array_length=${#my_array[@]}

Now the length is stored in my_array_length.

现在长度存储在my_array_length中。

#2


35  

The other answers will break if output of command contains spaces (which is rather frequent) or glob characters like *, ?, [...].

如果命令的输出包含空格(非常频繁)或诸如*、?、[…]等通配符,则其他答案将失效。

To get the output of a command in an array there are essentially 2 ways:

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

  1. With Bash≥4 use mapfile—it's the most efficient:

    使用Bash≥4 mapfile-it最有效:

    mapfile -t my_array < <( my_command )
    
  2. Otherwise, a loop reading the output (slower, but safe):

    否则,读取输出的循环(较慢,但安全):

    my_array=()
    while IFS= read -r line; do
        my_array+=( "$line" )
    done < <( my_command )
    

You'll probably see a lot of this:

你可能会看到很多这样的东西:

my_array=( $( my_command) )

But don't use it! Look how it's broken:

但不要使用它!看它坏了:

$ # 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!

Then some people would recommend using IFS=$'\n' to fix this:

然后一些人建议使用IFS=$'\n'来解决这个问题:

$ IFS=$'\n'
$ my_array=( $(echo "one two"; echo "three four") )
$ declare -p my_array
declare -a my_array='([0]="one two" [1]="three four")'
$ # It works!

But now let's use another command:

现在让我们使用另一个命令:

$ 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?

That's because I have a file called t in the current directory… and this filename is matched by the glob [three four]… at this point some people would recommend using set -f to disable globbing: but look at it: you have to change IFS and use set -f to be able to fix a broken technique (and you're not even fixing it really)! when doing that we're really fighting against the shell, not working with the shell.

那是因为我有一个名为t的文件在当前目录中,这个文件名匹配通配符匹配操作符(三四个)……在这一点上有些人会建议使用- f设置为禁用globbing:但是看:你必须改变IFS和使用- 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]")'

here we're working with the shell!

这是我们用壳做的!

#3


4  

Imagine that you are going to put the files and directory names (under the current folder) to an array and count its items. The script would be like;

假设您要将文件和目录名(在当前文件夹下)放在一个数组中,并对其项进行计数。剧本是这样的;

my_array=( `ls` )
my_array_length=${#my_array[@]}
echo $my_array_length

Or, you can iterate over this array by adding the following script:

或者,您可以通过添加以下脚本对该数组进行迭代:

for element in "${my_array[@]}"
do
   echo "${element}"
done

#1


53  

You can use

您可以使用

my_array=( $(<command>) )

to store the output of command <command> into the array my_array.

将命令的输出存储到数组my_array中。

You can access the length of that array using

您可以使用

my_array_length=${#my_array[@]}

Now the length is stored in my_array_length.

现在长度存储在my_array_length中。

#2


35  

The other answers will break if output of command contains spaces (which is rather frequent) or glob characters like *, ?, [...].

如果命令的输出包含空格(非常频繁)或诸如*、?、[…]等通配符,则其他答案将失效。

To get the output of a command in an array there are essentially 2 ways:

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

  1. With Bash≥4 use mapfile—it's the most efficient:

    使用Bash≥4 mapfile-it最有效:

    mapfile -t my_array < <( my_command )
    
  2. Otherwise, a loop reading the output (slower, but safe):

    否则,读取输出的循环(较慢,但安全):

    my_array=()
    while IFS= read -r line; do
        my_array+=( "$line" )
    done < <( my_command )
    

You'll probably see a lot of this:

你可能会看到很多这样的东西:

my_array=( $( my_command) )

But don't use it! Look how it's broken:

但不要使用它!看它坏了:

$ # 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!

Then some people would recommend using IFS=$'\n' to fix this:

然后一些人建议使用IFS=$'\n'来解决这个问题:

$ IFS=$'\n'
$ my_array=( $(echo "one two"; echo "three four") )
$ declare -p my_array
declare -a my_array='([0]="one two" [1]="three four")'
$ # It works!

But now let's use another command:

现在让我们使用另一个命令:

$ 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?

That's because I have a file called t in the current directory… and this filename is matched by the glob [three four]… at this point some people would recommend using set -f to disable globbing: but look at it: you have to change IFS and use set -f to be able to fix a broken technique (and you're not even fixing it really)! when doing that we're really fighting against the shell, not working with the shell.

那是因为我有一个名为t的文件在当前目录中,这个文件名匹配通配符匹配操作符(三四个)……在这一点上有些人会建议使用- f设置为禁用globbing:但是看:你必须改变IFS和使用- 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]")'

here we're working with the shell!

这是我们用壳做的!

#3


4  

Imagine that you are going to put the files and directory names (under the current folder) to an array and count its items. The script would be like;

假设您要将文件和目录名(在当前文件夹下)放在一个数组中,并对其项进行计数。剧本是这样的;

my_array=( `ls` )
my_array_length=${#my_array[@]}
echo $my_array_length

Or, you can iterate over this array by adding the following script:

或者,您可以通过添加以下脚本对该数组进行迭代:

for element in "${my_array[@]}"
do
   echo "${element}"
done