我什么时候在Bash中将IFS设置为换行符?

时间:2017-02-06 05:05:57

标签: arrays bash ifs

我认为将IFS设置为$'\n'可以帮助我将整个文件读入数组,如:

IFS=$'\n' read -r -a array < file

但是,上面的命令只将文件的第一行读入数组的第一个元素,而不是其他内容。

即使只读取数组中的第一行:

string=$'one\ntwo\nthree'
IFS=$'\n' read -r -a array <<< "$string"

我在本网站上发现其他帖子,讨论使用mapfile -tread循环将文件读入数组。

现在我的问题是:我何时才使用IFS=$'\n'

2 个答案:

答案 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'

  • 如图所示,如果你想将文件读入一个数组,每个元素一行,如果你的Bash早于4.0,你不想使用循环
  • Some people promote使用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) )

或最后,您可以使用IFSreadarray

readarray array <filename

尝试一下,如果您有疑问,请告诉我。