我认为将IFS设置为$'\n'
可以帮助我将整个文件读入数组,如:
IFS=$'\n' read -r -a array < file
但是,上面的命令只将文件的第一行读入数组的第一个元素,而不是其他内容。
即使只读取数组中的第一行:
string=$'one\ntwo\nthree'
IFS=$'\n' read -r -a array <<< "$string"
我在本网站上发现其他帖子,讨论使用mapfile -t
或read
循环将文件读入数组。
现在我的问题是:我何时才使用IFS=$'\n'
?
答案 0 :(得分:4)
你的第二次尝试几乎可行,但是你必须告诉read
它不应该只读到换行符(默认行为),但是例如直到空字符串:
$ IFS=$'\n' read -a arr -d '' <<< $'a b c\nd e f\ng h i'
$ declare -p arr
declare -a arr='([0]="a b c" [1]="d e f" [2]="g h i")'
但正如您所指出的那样,mapfile
/ readarray
是您的方法(需要Bash 4.0或更新版本):
$ mapfile -t arr <<< $'a b c\nd e f\ng h i'
$ declare -p arr
declare -a arr='([0]="a b c" [1]="d e f" [2]="g h i")'
-t
选项会删除每个元素的换行符。
至于何时想使用IFS=$'\n'
:
IFS
,没有空格,以避免字拆分带来意外的副作用;不过,在我看来,正确的方法是理解单词拆分,并确保通过适当的引用来避免它。IFS=$'\n'
,例如the one for cd
in bash-completion:此脚本摆弄路径并用冒号替换冒号,然后使用IFS
拆分它们。 答案 1 :(得分:4)
你对 IFS 的含义感到困惑。 IFS 是bash用于执行分词到分割行到字词的内部字段分隔符 扩张后。默认值为[ \t\n]
(空格,制表符,换行符)。
通过重新分配IFS=$'\n'
,您正在删除' \t'
并告诉bash仅在newline
字符上拆分字词(您的想法是正确的)。这样就可以在不引用的情况下将some line with spaces
读入单个数组元素。
您的实施失败的地方在read -r -a array < file
。 -a
会将行中的单词分配给顺序数组索引。但是,你告诉bash只能打破newline
(这就是整行)。由于您只调用一次读取,因此只填充一个数组索引。
您可以这样做:
while IFS=$'\n' read -r line; do
array+=( $line )
done < "$filename"
(如果您只是引用IFS
,则可以在不更改"$line"
的情况下执行此操作)
或者使用IFS=$'\n'
,您可以
IFS=$'\n'
array=( $(<filename) )
或最后,您可以使用IFS
和readarray
:
readarray array <filename
尝试一下,如果您有疑问,请告诉我。