如何在 EOF 处删除多个换行符?

Ben*_*ngt 28 bash sed awk ed

我有以一个或多个换行符结尾的文件,并且应该只以一个换行符结尾。我如何使用 Bash/Unix/GNU 工具做到这一点?

坏文件示例:

1\n
\n
2\n
\n
\n
3\n
\n
\n
\n
Run Code Online (Sandbox Code Playgroud)

示例更正文件:

1\n
\n
2\n
\n
\n
3\n
Run Code Online (Sandbox Code Playgroud)

换句话说:在 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)
Run Code Online (Sandbox Code Playgroud)

澄清:当然,管道是允许的,如果这样更优雅的话。

Ale*_*lko 29

来自有用的 sed 单行脚本

# Delete all trailing blank lines at end of file (only).
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' file
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我使用以下方法为多个文件执行了以下操作:`find . -type f -name '*.js' -exec sed --in-place -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \ ;` (5认同)

Hau*_*ing 20

awk '/^$/ {nlstack=nlstack "\n";next;} {printf "%s",nlstack; nlstack=""; print;}' file
Run Code Online (Sandbox Code Playgroud)

  • +1:awk 的解决方案(几乎)总是优雅且可读的! (3认同)

llu*_*lua 19

由于您已经使用更合适的工具 sed 和 awk 获得了答案;您可以利用$(< file)去除尾随空白行的事实。

a=$(<file); printf '%s\n' "$a" > file
Run Code Online (Sandbox Code Playgroud)

那个廉价的 hack 无法删除可能包含空格或其他非打印字符的尾随空行,只能删除尾随空行。如果文件包含空字节,它也不起作用。

在比bash和zsh的其他外壳,使用$(cat file)代替$(<file)

  • @OlivierDulac `$()` 丢弃尾随的换行符。这是一个设计决定。我认为这将使其他字符串中的集成更容易:`echo "On $(date ...) we will meet."` 几乎每个 shell 命令在最后输出的换行符都是邪恶的。 (3认同)

slm*_*slm 5

您可以将此技巧与cat& 一起使用printf

$ printf '%s\n' "`cat file`"
Run Code Online (Sandbox Code Playgroud)

例如

$ printf '%s\n' "`cat ifile`" > ofile
$ cat -e ofile
1$
$
2$
$
$
3$
Run Code Online (Sandbox Code Playgroud)

$表示线的末尾。

参考