Perl一个衬垫去除多条线

时间:2013-10-07 07:34:30

标签: regex perl

输入文件是

<section_begin>  mxsqlc


*** WARNING[13052] Cursor C is not fetched.
<section_end>
<section_begin>  b2.lst
*


*** WARNING[13052] Cursor C is not fetched.

0 errors, 1 warnings in SQL C file "b2.ppp".
<section_end>
<section_begin>  b2s0
SQLCODE=0
SQLSTATE=00000
a=10, b=abc, c=20
SQLCODE=0
SQLSTATE=00000
a=10, b=abc      , c=10, d=xyz      
<section_end>

期望输出不低于线。

<section_end>
<section_begin>  b2s0

我的代码是

perl -ne 'print unless /^\<section_end\>(\s*|.*lst)?\s*$/' b2exp

删除所有<section_end>行,但不删除此行<section_begin> *.lst

2 个答案:

答案 0 :(得分:2)

保持简单

perl -ne 'print unless /^\<section_/' b2exp

有点复杂

perl -ne 'print unless /^\<section_(end|begin)\>/' b2exp

啊,你的问题不明确。 (对我来说,也许是真的)

我现在读作了 “我有一些标有<section_begin> tagname的部分 在开始时和最后</section_end>。   我希望在示例中排除具有特定标记名bs20的部分。我希望保留所有其他方面 “

perl -ne 'BEGIN {$p=1}  $p=0 if /section_begin.*b2s0/; print if $p; $p=1 if /<section_end>/;' ex.txt

答案 1 :(得分:0)

如果打算将带有lst的部分与下一部分合并(并在下一部分的开始标记之后移除同一行上的内容),我会选择使用Awk。

awk '/<section_end>/ && lst { next }
    /<section_begin>/ && lst { lst=0; next }
    /<section_begin>.*lst/ {lst=1}
    1' b2exp

当然,在Perl中可以做同样的事情;由于缓冲,带有perl -0777 -pe 's/.../.../s' file的最简单的单行内存将大大降低内存效率。

perl -0777 -pe 's%(<section_begin>[^\n]*lst.*?)\n<section_end>\n<section_begin>[^\n]%$1%s' b2exp

这会将整个文件读入内存(-0777)并替换多行正则表达式。贪婪的匹配.*?将使匹配尽可能短,即不超过模式其余部分的匹配(换行符,结束标记,换行符,开始标记可选地后跟非换行数据)。我们还要注意使用[^\n]我们希望在同一行保持匹配,因为/s标志会将.转换为可以匹配换行符的通配符。