【问题标题】:When do I set IFS to a newline in Bash?什么时候在 Bash 中将 IFS 设置为换行符?
【发布时间】:2017-06-22 23:20:51
【问题描述】:

我认为将 IFS 设置为 $'\n' 将有助于我将整个文件读入数组,如下所示:

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

但是,上面的命令只是将文件的第一行读入数组的第一个元素中,没有别的。

即使这样也只读取数组的第一行:

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

我在这个网站上看到了其他帖子,其中讨论了使用 mapfile -tread 循环将文件读入数组。

现在我的问题是:我什么时候使用IFS=$'\n'

【问题讨论】:

标签: arrays bash ifs


【解决方案1】:

您的第二次尝试几乎可以正常工作,但您必须告诉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 将它们拆分。

【讨论】:

    【解决方案2】:

    您对 IFS 是什么感到有些困惑。 IFSInternal Field Separator 被 bash 用来执行 分词 以将 拆分成 展开后。默认值为[ \t\n](空格、制表符、换行符)。

    通过重新分配IFS=$'\n',您将删除' \t' 并告诉bash 仅在newline 字符上拆分单词(您的想法是正确的)。这具有允许some line with spaces 被读入单个数组元素而不引用的效果。

    你的实现失败的地方是你的read -r -a array &lt; file-a 导致将行中的单词分配给顺序数组索引。但是,您告诉 bash 只在 newline (即整行)上中断。由于只调用了一次 read,因此只填充了一个数组索引。

    你可以这样做:

    while IFS=$'\n' read -r line; do
        array+=( $line )
    done < "$filename"
    

    (如果您只是引用 "$line",您可以在不更改 IFS 的情况下这样做)

    或者使用IFS=$'\n',你可以这样做

    IFS=$'\n'
    array=( $(<filename) )
    

    或者最后,您可以使用IFSreadarray

    readarray array <filename
    

    试试看,如果您有任何问题,请告诉我。

    【讨论】:

    • 不应该 array=$( $(&lt;filename) )array=( $(&lt;filename) )
    • 谢谢你们——本杰明和大卫。您的回答对我帮助很大。
    • 很高兴我们能提供帮助。在这两个答案之间,您现在应该对IFS 有一个很好的感觉。 word-splittingexpansion 这两个术语以及 bash 如何应用它们可能需要更长的时间才能适应——这很正常,随着时间的推移它会逐渐消失。别忘了man bash,它什么都有,只是需要一段时间才能弄清楚如何舒适地阅读它。当您可以通过简单的 man bash/searchterm 找到所需的内容时,您就可以很好地掌握 shell。祝你的脚本好运:)
    猜你喜欢
    • 1970-01-01
    • 2018-02-09
    • 2013-10-12
    • 2010-10-10
    • 2017-08-27
    • 1970-01-01
    • 2020-03-15
    • 2018-12-05
    相关资源
    最近更新 更多