【问题标题】:Bash Script Looping over line inputBash 脚本在行输入上循环
【发布时间】:2011-09-03 01:14:48
【问题描述】:

我正在执行以下操作,基本上可以。 该脚本尝试在文件中插入一些行来重写它。

但它正在剥离所有空白行以及所有行填充。 主要问题是它不处理文件的最后一行。 我不知道为什么。

     while read line; do
        <... process some things ...>
        echo ${line}>> "${ACTION_PATH_IN}.work"
     done < "${ACTION_PATH_IN}"

可以做些什么来解决这个问题?

【问题讨论】:

    标签: bash loops


    【解决方案1】:
    while IFS= read -r line; do
        ## some work
        printf '%s\n' "$line" >> output
    done < <(printf '%s\n' "$(cat input)")
    
    • 一个空的 IFS 告诉 read 不要去除前导和尾随空格。
    • read -r 防止 EOL 处的反斜杠创建续行。
    • 双引号您的参数替换 ("$line") 以防止 shell 对其值进行分词和通配。
    • 使用printf '%s\n' 而不是echo,因为它在处理-e-n 等值时是可靠的。
    • &lt; &lt;(printf '%s\n' "$(cat input)") 是 LF 终止 input 内容的丑陋方式。其他构造是可能的,具体取决于您的要求(如果您的整个 while 可以在子外壳中运行,则使用管道而不是从进程替换重定向)。
      如果在处理它之前确保它是 LF 终止的,可能会更好。

    【讨论】:

    • 如果IFS 已设置为读取,则不需要最后一个printf,因为read 实际上会逐字读取所有行(包括空格),因为cat 只是对文件内容不做任何事情,而是将它们复制到管道中。
    • @Diego: printf ' foo \n\n bar ' | bash -c 'while IFS= read -r line; do printf "&lt;&lt;%s&gt;&gt;\n" "$line"; done' 从不处理最后的非 LF 终止的“bar”行。来自进程替换的重定向中的printf 用于添加尾随LF if-and-only-if-and-only-如果原始内容没有;这不是要保留空格,而是要正确处理最后一行。
    • @Diego:你是对的,read 将读取最终的非 LF 终止行,但它也返回非零,退出循环(因此这样的行永远不会被循环体)。
    • 啊,我明白了...重要的是确保最后一行以换行符结尾...容易得多:)
    【解决方案2】:

    最好的办法是使用awk 之类的工具,而不是shell 的while 循环。首先,awk 用于解析/操作文件,因此对于要处理的大文件,awk 具有优势。其次,您不必关心是否有最后一个换行符(对于您的情况)。

    因此相当于您的 while read 循环:

    awk '{
      # process lines
      # print line > "newfile.txt"
    }' file 
    

    【讨论】:

      【解决方案3】:

      不读取最后一行的一个可能原因是文件没有以换行符结尾。总的来说,我希望它能够工作,但这可能就是原因。

      在 MacOS X (10.7.1) 上,我得到了这个输出,这就是你看到的行为:

      $ /bin/echo -n Hi
      Hi$ /bin/echo -n Hi > x
      $ while read line; do echo $line; done < x
      $
      

      明显的解决方法是确保文件以换行符结尾。

      【讨论】:

        【解决方案4】:

        首先,使用

        echo "$line" >> ...
        

        注意引号。如果你不放它们,shell 本身会移除填充。

        至于最后一行,很奇怪。这可能与文件的最后一行是否以\n 终止有关(这样做是一个好习惯,几乎所有编辑器都会为您这样做)。

        【讨论】:

          猜你喜欢
          • 2016-08-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-09
          • 1970-01-01
          相关资源
          最近更新 更多