如何将多行合并为单行,但仅限于由空行分隔的行块

问题描述 投票:3回答:6

我试图将多行合并为单行,但有其他条件。

我的输入文件如下:

Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 - 
  D1stuff6 )

+ D2*(D2stuff)

所以有多条线也用空行分隔。所有*stuff*都包含长而复杂的表达式,也可以包含括号。

I want to keep the blank lines as it is but merge the other multiple lines.

预期的产出是

Dm1*(  stuff1 + stuff2 - stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 )

+ D2*(D2stuff)

所有目前的尝试都喜欢

awk '{printf("%s",$0)}' 

把所有东西都放在一行。我应该循环过线还是有任何方法来识别空行之间的块并应用一些东西?

bash awk sed sh
6个回答
4
投票

甚至比John1024的版本短一点

awk 'BEGIN { RS=""; ORS="\n\n"}{$1=$1}1'

要么

awk -v RS="" -v ORS="\n\n" '{$1=$1}1'

使用RS=""告诉awk使用任何段落作为记录(即由空行分隔的文本块)。但它也告诉awk a 始终是与...结合的字段分隔符 FS。通过重新定义输出记录分隔符ORS,我们可以通过重置第一个记录$0告诉awk重新定义其记录$1=$1,输出所有内容。这样,由FS定义的所有字段分隔符(此处的默认值)和换行符(由于RS="")都被OFS替换(默认为a )。最后我们打印记录 1

当你另外设置OFS=""时,你可以摆脱所有的空间

RS RS字符串值的第一个字符应为输入记录分隔符;一个 默认情况下。如果 RS包含多个字符,结果未指定。如果RSnull,则记录由a组成的序列分隔 加上一个或多个空白行,前导或尾随空白行不应在输入的开头或结尾处产生空记录,并且 无论价值如何,都应始终是一个字段分隔符 FS是。

来源:POSIX awk standard


4
投票
awk '{if(NF!=0){printf $0}else{printf "\n\n"}}'

2
投票

尝试:

$ awk -v RS=  '{gsub(/ *\n */, " "); print $0 ORS}' file
Dm1*(  stuff1 + stuff2 - stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 )

+ D2*(D2stuff)

这个怎么运作:

  • -v RS= 这告诉awk使用空行作为记录分隔符。
  • gsub(/ *\n */, " ") 这告诉awk用一个空格替换记录中的任何换行符以及任何周围的空格。
  • print $0 ORS 这告诉awk打印记录后跟一个输出记录分隔符ORS,默认情况下是一个换行符。

2
投票

除了由awk引入的非常漂亮的John1024命令之外,您还可以使用sed方法解决您的问题。

输入:

$ cat input_file 
Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 -
  D1stuff6 )

+ D2*(D2stuff)

命令:

sed -n '/^$/!{H};/^$/{x;s/\n//g;s/$/\n/;p;};${x;s/\n//g;p}' input_file

输出:

Dm1*(  stuff1 + stuff2 -stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +  D1stuff5 -  D1stuff6 )

+ D2*(D2stuff)

说明:

  • -n停用sed自动打印
  • /^$/!{H};sed遇到非空线时,/^$/!通过H将此线附加到保留空间
  • /^$/{x;s/\n//g;s/$/\n/;p;}sed遇到空行/^$/,交换持有空间和模式空间x,删除所有\n在已构建s/\n//g的字符串,在字符串\n的末尾添加s/$/\n/,打印它p
  • ${x;s/\n//g;p}到达最后一行时,sed,交换持有/模式空间x,然后通过\n删除所有s/\n//g,然后打印它p

1
投票

使用Perl段落模式

perl -00 -ne ' s/\n//g; print "$_\n\n" ' file

与您的输入

$ cat bogey.txt
Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +
  D1stuff5 -
  D1stuff6 )

+ D2*(D2stuff)
$ perl -00 -ne ' s/\n//g; print "$_\n\n" ' bogey.txt
Dm1*(  stuff1 + stuff2 -stuff3 + stuff4)

+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 +  D1stuff5 -   D1stuff6 )

+ D2*(D2stuff)

$

1
投票

这可能适合你(GNU sed):

sed ':a;N;/\n$/!s/\n//;ta' file

收集图案空间中的线条,删除换行符,直到空行。

© www.soinside.com 2019 - 2024. All rights reserved.