如何将多行合并为一行,但仅适用于由空白行分隔的行块

时间:2019-03-31 23:28:14

标签: bash awk sed sh

我正在尝试将多行合并为一条,但要有附加条件。

我的输入文件如下:

Dm1*(  stuff1 + stuff2 -
stuff3 + stuff4)

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

+ D2*(D2stuff)

因此,有多行也被空白行分隔。所有*stuff*都包含冗长而复杂的表达式,其中也可能包含括号。

我想保留空白行,但合并其他多行。

预期输出为

Dm1*(  stuff1 + stuff2 - stuff3 + stuff4)

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

+ D2*(D2stuff)

所有当前尝试

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

将所有内容放在一行中。我应该遍历行还是有什么方法可以识别空白行之间的块并将其应用于其中?

6 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

甚至比John1024的版本短

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

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

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

打印记录

额外设置OFS=""

可以消除所有空格
  

RS 字符串值RS的第一个字符应为输入记录分隔符;默认情况下为。如果RS包含多个字符,则结果不确定。如果RSnull,则记录由由加上一个或多个空行组成的序列分隔,前导或尾随空行不应导致记录开头或末尾的记录为空。输入,无论FS的值是什么,都应始终是字段分隔符。

     

来源:POSIX awk standard

答案 2 :(得分: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,默认情况下它是换行符。

答案 3 :(得分:2)

除了John1024引入的非常漂亮的<div> <new-component _ngcontent-c3=""></new-component> </div> 命令之外,您还可以使用awk方法解决问题。

输入:

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

答案 4 :(得分: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)

$

答案 5 :(得分:1)

这可能对您有用(GNU sed):

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

在模式空间中收集行,删除换行符,直到空行。