我在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
幕后发生了什么事?这两种不同的"类型"数组?
答案 0 :(得分:2)
在您的第一个示例foo=$(cat file)
中,您现在拥有foo变量,其中包含字符串,即文件的内容。 echo $foo
和echo "$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