关于bash数组的澄清:从函数输出加载而不是从循环加载

时间:2015-03-19 18:20:00

标签: arrays bash

我在bash数组中看到过两种不同的行为,我无法理解其基本性质:

第一个例子是每当我将多行输出捕获到变量时。我能够通过回显数组的名称来回显所有数据:

[bennett@pc foo]$ foo=`cat filea.c`
[bennett@pc foo]$ echo $foo
asfed asdf asdf asd fasd fas dfs dfsd f sd d ddd
[bennett@pc foo]$ echo "$foo"
asfed
asdf
asdf
asd
fasd
fas
dfs
dfsd
f
sd
d
ddd

但是当我使用for循环加载另一个具有相同数据的数组时,必须迭代新数组才能回显所有输出,因为回显名称似乎只输出第一个元素:

[bennett@pc foo]$ for i in $foo
> do
> otherarray+=( $i )
> done
[bennett@pc foo]$ echo $otherarray
asfed
[bennett@pc foo]$ for i in ${otherarray[@]}
> do
> echo "$i"
> done
asfed
asdf
asdf
asd
fasd
fas
dfs
dfsd
f
sd
d
ddd

幕后发生了什么事?这两种不同的"类型"数组?

1 个答案:

答案 0 :(得分:2)

在您的第一个示例foo=$(cat file)中,您现在拥有foo变量,其中包含字符串,即文件的内容。 echo $fooecho "$foo"之间的差异是分词 - 请参阅shell扩展列表:https://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions

在第二个示例中,您使用分词来迭代变量内容的单词,并将这些单词存储到数组中。

当你echo $arrayname时,你只得到数组的第一个元素。

当你不引用数组扩展 - for i in ${otherarray[@]}时 - 再次,你要对数据进行分词。

一个例子:

$ cat file
one  two
three  four

# using the bash builtin for `cat file`
$ foo=$(< file)
$ echo $foo
one two three four
$ echo "$foo"
one  two
three  four

现在,让我们使用数组

$ for word in $foo; do
words+=($word)
done
$ echo $words
one

# without quotes
$ printf "%s\n" ${words[@]}
one
two
three
four

# with quotes
$ printf "%s\n" "${words[@]}"
one
two
three
four

我们可以看到每个元素都是文件中的,而不是

让我们使用内置mapfile命令

$ mapfile -t words < file

# without quotes
$ printf "%s\n" ${words[@]}
one
two
three
four

# with quotes
$ printf "%s\n" "${words[@]}"
one  two
three  four

我怀疑你想要的是将文件的每一行存储为数组元素。

迭代文件的的另一种方法是while(非for)循环:

while IFS= read -r line; do    # use `IFS=` to avoid trimming whitespace
                               # and `read -r` to avoid messing with backslashes
    array+=("$line")           # use quotes
done < file

<强> TL;博士

  • 总是引用您的"$variables",除非您确切知道何时关闭引号。
  • 使用其中一个构造来迭代文件行

    mapfile -t array < file
    while IFS= read -r line; do ...; done < file