假设您有以下文件:
$ cat /tmp/test.txt
Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR
有四个元素会改变许多Bash解决方案读取的文件输出的含义:
- 空白行4;
- 两条线上的前导或尾随空格;
- 保持各行的含义(即每行都是一条记录);
- 线路6未以CR终止。
如果要文本文件一行一行地包括空白行和不带CR的终止行,则必须使用while循环,并且必须对最后一行进行替代测试。
以下是可能更改文件的方法(与cat
返回内容相比):
1)丢失最后一行以及前导和尾随空格:
$ while read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
(如果while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
改为这样做,则保留前导和尾随空格,但是如果最后一行没有以CR终止,则仍然会丢失最后一行)
2)使用with进行流程替换cat
将一口气读取整个文件,并且失去了各行的含义:
$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
Line 2 has leading space
Line 3 followed by blank line
Line 5 (follows a blank line) and has trailing space
Line 6 has no ending CR'
(如果"
从$(cat /tmp/test.txt)
文件中逐个读取文件而不是一个文件,则可能不是目的。)
逐行读取文件并保留所有间距的最可靠,最简单的方法是:
$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
' Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space '
'Line 6 has no ending CR'
如果要去除前导和交易空间,请删除IFS=
零件:
$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
'Line 6 has no ending CR'
没有终止(文本文件\n
,而相当普遍,被认为是POSIX断下。如果你能在后指望\n
你不需要|| [[ -n $line ]]
在while
循环中。)
有关BASH常见问题的更多信息