删除两个模式之间出现的所有新行(sed或awk?)

时间:2015-10-14 08:24:12

标签: bash awk sed

我有一个简单的问题。我需要删除\ n两个模式之间的所有出现。即

<INFOSTART
A=1
B=2
C=3
D=4
<INFOEND
<INFOSTART
G=1
Z=3
<INFOEND

所以我希望输出类似于

A=1 B=2 C=3 D=4
G=1 Z=3

任何想法我怎么能这样做?并提前感谢你们..

4 个答案:

答案 0 :(得分:4)

trsed

AMD$ tr '\n' ' ' < File | sed 's/<INFOSTART //g; s/<INFOEND /\n/g'
A=1 B=2 C=3 D=4
G=1 Z=3

首先将所有newlines替换为space。然后使用sed删除所有<INFOSTART,并将所有<INFOEND替换为newlines

答案 1 :(得分:3)

您可以使用带有awk的简单状态机,例如使用以下输入文件,稍加修改以允许文本之外标记(如果没有此类文本,则仍将按预期工作,这只是为了处理额外的案例):

xyzzy
plugh
<INFOSTART
A=1
B=2
C=3
D=4
<INFOEND
twisty
passages
<INFOSTART
G=1
Z=3
<INFOEND
after
last

使用这样的数据文件(或您的原始文件),以下awk命令可以为您提供所需的内容,将开始和结束标记之间的行组合成一行:

awk ' /^<INFOSTART$/ {inside=1; sep=""; next}
      /^<INFOEND$/   {inside=0; print ""; next}
      inside         {printf sep""$0; sep=" "; next}
                     {print}' input_file

xyzzy
plugh
A=1 B=2 C=3 D=4
twisty
passages
G=1 Z=3
after
last

更详细地检查awk代码,以下各节展开每一行。

只要找到仅包含起始标记的行,就会运行以下分段。它将inside状态设置为true(非零)以指示您应该开始组合行,并将初始分隔符设置为空字符串以确保组合行上没有前导空格。 next只是立即抓住下一个输入行,开始一个新的循环:

/^<INFOSTART$/ {inside=1; sep=""; next}

假设您没有找到开始标记,则此段将运行结束标记。如果找到,则将inside状态设置回false(零)以开始完全按输出文件中显示的方式打印输出行。它还输出换行符以正确完成组合线,然后使用下一个输入行重新开始循环:

/^<INFOEND$/   {inside=0; print ""; next}

如果您确定该行既不是开始也不是结束标记,则您的行为取决于inside状态。对于true,您需要将输入行组合成单个输出行,因此您只需打印分隔符后跟行本身,而不使用尾随换行符。然后将分隔符设置为空格,以便下一个输入行与前一个输入行正确分离。然后它循环返回下一个输入行:

inside         {printf sep""$0; sep=" "; next}

最后,如果你到了这里,你知道你在开始/结束部分之外,所以你只需要在输入文件中完全回显该行:

               {print}'

如果您不想要格式良好的版本,则可以使用以下缩小版本,假设您确定唯一的<INFO...行是开始和结束标记:

awk '/^<INFOS/{a=1;b="";next}/^<INFOE/{a=0;print"";next}a{printf b$0;b=" ";next}1'

然而,由于这可能是一个脚本而不是单行命令,我自己会倾向于使用可读版本。

答案 2 :(得分:1)

Perl救援:

< input perl -ne 's/\n/ /, print if $s = /<INFOSTART/ .. ($e = /<INFOEND/)
                                    and $s > 1 and !$e;
                  print "\n" if $e'
当我们在标签之间(使用..运算符)时,

$ s为真。如果我们匹配结束标记,则$ e为真,当我们匹配开始标记时,$ s为1。

答案 3 :(得分:1)

这可能适合你(GNU sed):

sed '/^<INFOSTART/d;:a;N;/^<INFOEND/M!s/\n/ /;ta;P;d' file

这将删除以<INFOSTART<INFOEND开头的行,并用空格替换所有其他行之间的换行符。

可以进一步减少解决方案(提供文件格式正确):

sed '/^</d;:a;N;/^</M!s/\n/ /;ta;P;d' file