相关文章推荐
重感情的板凳  ·  scala ...·  2 月前    · 
温暖的机器人  ·  springboot + ...·  1 年前    · 
读研的红薯  ·  【问题解决】Error: ...·  1 年前    · 
爱健身的镜子  ·  python - Can't start ...·  1 年前    · 
3 个评论
TTT
严格来说,解决方案是否需要通过 sed
那么你所期望的输出仍然包含 \n\n ,但不包含 \n\n\n
有些版本的 cat -s --squeeze-blank ,用于用一个空行替换多个空行的序列。
linux
bash
sed
Sam Roberts
Sam Roberts
发布于 2014-12-17
8 个回答
potong
potong
发布于 2021-12-24
已采纳
0 人赞同

This might work for you (GNU sed):

sed '/^$/{:a;N;s/\n$//;ta}' file

这就用一个空行取代了多个空行。

然而,如果你想在每个非空行后放置一个空行,那么。

sed '/^$/d;G' file 

它删除了所有的空行,只在非空行上附加一个空行。

这样做效果很好:sed '/^$/{:a;N;s/\n$//;ta}' 文件
能否解释一下或链接到一个文档文件?这些大括号是序列化的数据吗?- 不要紧,它们是sed特有的命令。见sed手册。 grymoire.com/Unix/Sed.html
Adam Katz
Adam Katz
发布于 2021-12-24
0 人赞同

Sed并不擅长以编程方式检查多行的任务。 下面是我能得到的最接近的结果。

$ sed '/^$/{n;/^$/d}' file

其逻辑是:如果你发现一个空行,就看下一行。 如果下一行也是空白,就删除下一行。

这在最后并没有吞掉所有的线,因为它假设有一个有意的额外对子,并将两个\n\n减少为两个\n

要做到这一点的基本awk

$ awk 'NF > 0 {blank=0} NF == 0 {blank++} blank < 2' file

这使用了一个名为空白, which is zero when the number of fields (NF) is nonzero and increments when they are zero (a 空白 line). Awk's default action, printing, is performed when the number of consecutive 空白 lines is less than two.

但在 ghi 之后,还有2个以上的EOL。
@anubhava: 是的。 正如我所指出的,这就是 sed 能做的最好的事情。 这可以解决 "双倍换行 "的问题,但不能解决问题中给出的伪代码重码。 Awk是更优雅的解决方案。
anubhava
anubhava
发布于 2021-12-24
0 人赞同

使用awk(gnu或BSD),你可以做到。

awk -v RS= -v ORS='\n\n' '1' file

Also using perl:

perl -pe '$/=""; s/(\n)+/$1$1/' file
    
那个perl解决方案将把整个文件加载到内存中,这对非常大的文件来说是行不通的。
Zug
Zug
发布于 2021-12-24
0 人赞同

Found here 这就是我所看到的 (速度比 this solution ).

sed '/^$/N;/\n$/D' file

替换代码1】的字体可以读作如下。

If the next line is empty, delete the current line.

并可翻译成以下伪代码(对于已经熟悉sed的读者,buffer指的是模式空间)。

 1 | # sed '/^$/N;/\n$/D' file
 2 | while not end of file :
 3 |   buffer = next line
 4 |   # /^$/N
 5 |   if buffer is empty :                        # /^$/
 6 |     buffer += "\n" + next line                # N
 7 |   end if
 8 |   # /\n$/D
 9 |   if buffer ends with "\n" :                  # /\n$/
10 |     delete first line in buffer and go to 5   # D
11 |   end if
12 |   print buffer
13 | end while

在正则表达式/^$/中,^$符号分别表示 "缓冲区的开始 "和 "缓冲区的结束"。它们指的是缓冲区的边缘,而不是缓冲区的内容。

D命令执行以下任务:如果缓冲区包含新行,则删除缓冲区中直到第一个新行的文本,并重新启动程序循环(回到第1行),不处理其余命令,不打印缓冲区,也不读取新的输入行。

最后,请记住,sed在处理该行之前会删除尾部换行,请记住,print命令会将尾部换行加回来。因此,在上面的代码中,如果要处理的下一行是Hello World!\n,那么next line就暗指Hello World!

更多详情请见https://www.gnu.org/software/sed/manual/sed.html.

现在你已经准备好将该算法应用于以下文件。

Now let's see why this solution是更快。

替换代码1】脚本/^$/{:a;N;s/\n$//;ta}可读为:。

如果当前行符合/^$/,则做{:a;N;s/\n$//;ta}

由于在^$之间没有任何东西,我们可以这样重新表述。

If the current line is empty, then do {:a;N;s/\n$//;ta}.

这意味着sed对每个空行执行以下命令。

非空行则按原样打印。了解了这些,我们可以用下面的伪代码来描述整个过程。

 1 | # sed '/^$/{:a;N;s/\n$//;ta}' file
 2 | while not end of file :
 3 |   buffer = next line
 4 |   # /^$/{:a;N;s/\n$//;ta}
 5 |   if buffer is empty :               # /^$/
 6 |     :a                               # :a
 7 |     buffer += "\n" + next line       # N
 8 |     if buffer ends with "\n" :       # /\n$/
 9 |       remove last "\n" from buffer   # s/\n$//
10 |       go to :a (at 6)                # ta
11 |     end if
12 |   end if
13 |   print buffer
14 | end while

正如你所看到的,两个sed的脚本非常相似。事实上,s/\n$//;ta/\n$/D几乎相同。然而,第二个脚本跳过了第5步,所以它可能比第一个脚本快。让我们为这两个脚本输入~10Mb的空行进行计时。

$ yes '' | head -10000000 > file
$ /usr/bin/time -f%U sed '/^$/N;/\n$/D' file > /dev/null
$ /usr/bin/time -f%U sed '/^$/{:a;N;s/\n$//;ta}' file > /dev/null

Second script wins.

glenn jackman
glenn jackman
发布于 2021-12-24
0 人赞同
perl -00 -pe 1 filename

它将输入文件分成 "段落",并以2个或更多的换行符隔开,然后打印出以单个空行隔开的段落。

perl -00 -pe 1 <<END

第二条sed命令在每一行的末尾插入一个换行符。

OP要求用单空行替换双空行,而不是在每个非空行之间用单空行。
TTT
不,这可能是问题文本所暗示的,但他提供的例子清楚地表明,他希望将所有系列的空行变成单行空行。 也就是说,提问者对我的解决方案的回应表明,在某些情况下(不清楚什么时候),他不希望在非空行之间出现空行。
TTT
TTT
发布于 2021-12-24
0 人赞同

为什么不把所有的空行去掉,然后在每一行后面加一个空行? 对于一个输入文件 tmp ,正如你所指定的。

sed '/^$/d' tmp|sed '0~1 a\ '

如果空白处(空格和制表符)对你来说算作 "空白 "行,那么就用sed '/^\s*$/d' tmp|sed '0~1 a\ '代替。

请注意,这些解决方案确实在结尾处留下了一个尾部空行,因为我不确定这是否是需要的。 很容易删除。

有一些行应该在一起,如mno mno pqr
TTT
@SamRoberts 所以你是说,某些行之间不应该有空行? 如何知道哪些应该和不应该?
Potherca
Potherca
发布于 2021-12-24
0 人赞同

我不会为此使用 sed ,而是使用带有 -s 标志的 cat 。 正如手册中所说。

-s, --squeeze-blank    suppress repeated empty output lines