我找到了这个关于如何删除三重空行的问题和答案。但是,我只需要双空行。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 '/^$/{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
据我所知,这里的解决方案都不起作用。cat -s
正如@DerMike 所建议的那样,它不符合POSIX(如果您已经在使用sed
另一个转换,那么它就不那么方便了),并且sed 'N;/^\n$/d;P;D'
正如@Birei 所建议的那样,有时会删除比应有的更多的换行符。
相反,sed ':L;N;s/^\n$//;t L'
有效。对于 POSIX 合规性 use sed -e :L -e N -e 's/^\n$//' -e 't L'
,因为 POSIX 没有指定 using;
来分隔命令。
例子:
$ 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
and的空白行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'解决了我的问题。