【发布时间】:2022-01-13 18:47:21
【问题描述】:
我发现这个question and answer 关于如何删除三个空行。但是,我只需要双空行。 IE。所有双空行应完全删除,但应保留单个空行。
我知道一点 sed,但是删除三个空白行的建议命令让我头疼:
sed '1N;N;/^\n\n$/d;P;D'
【问题讨论】:
-
三个或更多的空行呢?
-
@xdazz: 是的,三个或更多空行都可以。
我发现这个question and answer 关于如何删除三个空行。但是,我只需要双空行。 IE。所有双空行应完全删除,但应保留单个空行。
我知道一点 sed,但是删除三个空白行的建议命令让我头疼:
sed '1N;N;/^\n\n$/d;P;D'
【问题讨论】:
使用cat 会更容易:
cat -s
【讨论】:
我评论了sed你不懂的命令:
sed '
## In first line: append second line with a newline character between them.
1N;
## Do the same with third line.
N;
## When found three consecutive blank lines, delete them.
## Here there are two newlines but you have to count one more deleted with last "D" command.
/^\n\n$/d;
## The combo "P+D+N" simulates a FIFO, "P+D" prints and deletes from one side while "N" appends
## a line from the other side.
P;
D
'
删除1N,因为我们只需要'堆栈'中的两行,第二个N就足够了,并将/^\n\n$/d;更改为/^\n$/d;以删除所有连续的两个空行。
测试:
infile的内容:
1
2
3
4
5
6
7
运行sed 命令:
sed '
N;
/^\n$/d;
P;
D
' infile
产生:
1
2
3
4
5
6
7
【讨论】:
sed -i 选项立即在文件中更改它,而不是将结果发送到输出流。
sed '/^$/{N;/^\n$/d;}'
它只会删除文件中两个连续的空白行。您只能在文件中使用此表达式,然后才能完全理解。当一个空行出现时,它将进入大括号。
通常 sed 会读取一行。 N 会将第二行附加到模式空间。如果该行是空行。这两行由换行符分隔。
/^\n$/ 这个模式将匹配那个时间只有d 可以工作。否则d 不起作用。 d 用于删除模式空间全部内容,然后开始下一个循环。
【讨论】:
使用awk 会更容易:
awk -v RS='\n\n\n' 1
【讨论】:
但上述解决方案只删除了第一次搜索 3 个连续空白行。 要删除所有,3个连续的空行使用下面的命令
sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' filename
【讨论】:
据我所知,这里的解决方案都不起作用。 @DerMike 建议的 cat -s 不符合 POSIX 标准(如果您已经在使用 sed 进行另一次转换,则不太方便),@Birei 建议的 sed 'N;/^\n$/d;P;D' 有时会删除比应有的更多的换行符。
相反,sed ':L;N;s/^\n$//;t L' 有效。对于 POSIX 合规性,请使用 sed -e :L -e N -e 's/^\n$//' -e 't L',因为 POSIX 未指定使用 ; 来分隔命令。
例子:
$ S='foo\nbar\n\nbaz\n\n\nqux\n\n\n\nquxx\n';\
> paste <(printf "$S")\
> <(printf "$S" | sed -e 'N;/^\n$/d;P;D')\
> <(printf "$S" | sed -e ':L;N;s/^\n$//;t L')
foo foo foo
bar bar bar
baz baz baz
qux
qux
qux quxx
quxx
quxx
$
在这里,我们可以并排查看原始文件、@Birei 的解决方案和我的解决方案。 @Birei 的解决方案删除了分隔 baz 和 qux 的所有空白行,而我的解决方案按预期删除了所有空行。
解释:
:L Create a new label called L.
N Read the next line into the current pattern space,
separated by an "embedded newline."
s/^\n$// Replace the pattern space with the empty pattern space,
corresponding to a single non-embedded newline in the output,
if the current pattern space only contains a single embedded newline,
indicating that a blank line was read into the pattern space by `N`
after a blank line had already been read from the input.
t L Branch to label L if the previous `s` command successfully
substituted text in the pattern space.
实际上,这一次删除一个重复出现的空行,将每个空行作为嵌入的换行符读入模式空间,N 并用s 删除它们。
【讨论】:
但上述解决方案只删除了第一次搜索 3 个连续空白行。要删除所有,3个连续的空行使用下面的命令
sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' 文件名
【讨论】:
只需将其通过管道传递给“uniq”命令,所有空行,无论它们的数量如何,都将缩小到只有一个。越简单越好。
澄清:正如 Marlar 所说,如果您不想删除“其他非空白连续重复行”,这不是解决方案。这是在其他情况下的解决方案,例如在尝试清理配置文件时,这是我看到这个问题时所寻求的解决方案。我确实只是使用 'uniq' 解决了我的问题。
【讨论】: