我知道这个问题有多个实例,例如打印两种模式之间的所有行,独占,仅限第一个实例(在sed,AWK或Perl中) 但我的问题是这两种模式是否可能不配对 - 例如
给定输入
PATTERN1
bbb
ccc
ddd
eee
fff
PATTERN1
ggg
hhh
iii
PATTERN2
jjj
PATTERN2
kkk
我希望最短的范围作为输出:
ggg
hhh
iii
这可能吗?
您能否尝试仅在 GNUawk
中根据您显示的示例编写和测试以下内容。
awk '
/PATTERN1/ && found1 && !found2{
found1=found2=val=""
}
/PATTERN1/{
found1=1
next
}
/PATTERN2/{
found2=1
if(found1){
print val
}
found1=found2=val=""
next
}
{
val=(val?val ORS:"")$0
}
' Input_file
给定样本的输出将为:
ggg
hhh
iii
说明:为上述添加详细说明。
awk ' ##Starting awk program from here.
/PATTERN1/ && found1 && !found2{ ##Checking if PATTERN1 in current line and found1 is SET and found2 is NOT SET then do following.
found1=found2=val="" ##Nullifying found1, found2 and val variables here.
}
/PATTERN1/{ ##Checking condition if PATTERN1 is found then do following.
found1=1 ##Setting found1 here for flagging.
next ##next will skip all further statements from here.
}
/PATTERN2/{ ##Checking condition if PATTERN2 is found then do following.
found2=1 ##Setting found2 here for flagging.
if(found1){ ##Checking condition if found1 is SET then do following.
print val ##Printing val here.
}
found1=found2=val="" ##Nullifying found1, found2 and val here.
next ##next will skip all further statements from here.
}
{
val=(val?val ORS:"")$0 ##Creating val which has current line value and keep appending it with new line.
}
' Input_file ##Mentioning Input_file name here.
在awk
中,您可以通过保存PATTERN..
并在每次遇到PATTERN..
时进行比较来做到这一点。在两者之间,您将元素保存在数组中,当您有两个不匹配的模式时,您将输出数组的内容。否则,您将清空数组并重置计数器,例如
awk '! /PATTERN/ {
a[++n]=$0
}
/PATTERN/ {
if ($0 != lastptrn)
for (i=1; i<=n; i++)
print a[i]
delete a
n=0
lastptrn=$0
}
' file
输出
ggg
hhh
iii
如果Perl
恰好是您的选择,请您尝试:
perl -0777 -ne '/.*PATTERN1n(.*?)PATTERN2/s && print $1' input
结果:
ggg
hhh
iii
-0777
选项告诉Perl
一次啜饮所有行。- 正则表达式
s
选项告诉Perl
在元字符.
中包含换行符。 .*PATTERN1n
缠绕该位置直到上PATTERN1
结束。(.*?)
指定最短的匹配项,并将$1
分配给匹配的行。
另一个:
$ awk '
/PATTERN1/ { # at starting pattern
f=1 # flag up
b="" # reset buffer
next # to exclude the start pattern
}
/PATTERN2/ { # at ending pattern
print b # output buffer
exit # no need to continue to the end
}
f { # when flag up
b=b (b==""?"":ORS) $0 # buffer records
}' file
要包括开始和结束标记,请删除next
并将f {...}
移到/PATTERN2/ {...}
之前
这可能对你有用(GNU sed):
sed -n '/PATTERN2/{g;/PATTERN1/{s/[^n]*n//p;q}};H;/PATTERN1/h' file
概述:将PATTERN1
行复制到保留空间中,但不包括PATTERN2
行,然后打印保留空间减去第一行。
处理:将所有行附加到保留空间,当保留空间匹配时,将保留空间替换为PATTERN1
的内容。
当PATTERN2
匹配时,用保留空间覆盖模式空间,如果模式空间包含PATTERN1
,则删除第一行,打印模式空间的内容并退出。