2011-09-03 130 views
3

我正在做以下,基本上工作。 该脚本尝试在文件中插入一些行以重写它。Bash脚本通过循环输入循环

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

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

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

回答

5
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
  • < <(printf '%s\n' "$(cat input)")是LF的丑陋的方式终止的input内容时是可靠的。其他结构也是可能的,这取决于你的要求(如果你的整个while运行在一个子shell中,管道而不是从过程替换重定向)。
    如果您在处理之前确保它是LF终止的,那可能会更好。
+0

如果'IFS'已设置为读取,不需要最后'printf',因为'read'实际上将读取所有的行逐字(包括空格),因为'cat'只是对文件内容没有任何影响,但将它们复制到管道中。 –

+0

@Diego:'printf'foo \ n \ n bar'| bash -c'while IFS = read -r line;做printf“<<%s>> \ n”“$ line”; done''从不处理最终的非LF终止的“bar”行。来自流程替代的重定向中的'printf'是在那里添加一个尾随LF(如果原始内容没有一个;这不是关于保留空白,而是要正确处理最后一行。 –

+0

@Diego:你是正确的,'read'将读取最终的非LF终止行,但它也返回非零值,它退出循环(因此这样的行绝不会被循环体处理)。 –

0

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

在MacOS X(10.7.1),我得到这个输出,这是您所看到的行为:

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

最明显的解决方法是,以确保该文件以换行符结束。

0

第一件事情,用

echo "$line" >> ... 

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

至于最后一行,这很奇怪。它可能与文件的最后一行是否由\n终止有关(这是一个很好的做法,几乎所有的编辑都会为你做这件事)。

3

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

因此您while read回路的等效:

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