我的文件以一个或多个换行符结尾,并且应该仅以一个换行符结尾。我如何使用 Bash/Unix/GNU 工具来做到这一点?
错误文件示例:
1\n
\n
2\n
\n
\n
3\n
\n
\n
\n
更正文件示例:
1\n
\n
2\n
\n
\n
3\n
换句话说:EOF 和文件的最后一个非换行符之间应该有一个换行符。
参考实现
读取文件内容,截掉一个换行符,直到末尾不再有两个换行符,然后写回:
#! /bin/python
import sys
with open(sys.argv[1]) as infile:
lines = infile.read()
while lines.endswith("\n\n"):
lines = lines[:-1]
with open(sys.argv[2], 'w') as outfile:
for line in lines:
outfile.write(line)
澄清:当然,如果更优雅的话,管道是允许的。
答案1
# Delete all trailing blank lines at end of file (only).
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' file
答案2
awk '/^$/ {nlstack=nlstack "\n";next;} {printf "%s",nlstack; nlstack=""; print;}' file
答案3
既然您已经通过更合适的工具 sed 和 awk 得到了答案;您可以利用$(< file)
删除尾随空白行的事实。
a=$(<file); printf '%s\n' "$a" > file
这种廉价的黑客方法无法删除可能包含空格或其他非打印字符的尾随空白行,只能删除尾随空行。如果文件包含空字节,它也将不起作用。
在 bash 和 zsh 以外的 shell 中,使用$(cat file)
代替$(<file)
.
答案4
这个问题被标记为编辑,但没有人提出ed
解决方案。
这是一个:
ed -s file <<'ED_END'
a
.
?.?+1,$d
w
ED_END
或者,等价地,
printf '%s\n' a '' . '?.?+1,$d' w | ed -s file
ed
启动时默认将您置于编辑缓冲区的最后一行。
第一个命令 ( a
) 在缓冲区末尾添加一个空行(编辑脚本中的空行就是这一行,点 ( .
) 只是用于返回命令模式)。
第二个命令的地址 ( ?.?
) 查找包含某些内容(甚至是空白字符)的最近的前一行,然后删除 ( d
) 从下一行开始到缓冲区末尾的所有内容。
第三个命令 ( w
) 将文件写回磁盘。
添加的空行可防止在原始文件末尾没有任何空行的情况下删除文件的其余部分。