Start_pattern
abc
d End_pattern
Start_pattern
abc
d
ef
ghij
klm
no End_pattern
Start_pattern
abc
def
hij End_pattern
Start_pattern
abc
dhi
jklm End_pattern
期望输出:
在包含Start_pattern
Search_pattern
开始和结束模式的End_pattern
之间打印行。
Start_pattern
abc
d
ef
ghij
klm
no End_pattern
Start_pattern
abc
def
hij End_pattern
在上述文件中,我想搜索"ef"
并在"Strat_pattern"
和"End_pattern"
之间打印行。
grep -B[NUM] and -A[NUM]
,因为它们可能没用
搜索模式“gef”和“Start_pattern”之间的行数未知
和“End_pattern”。grep
,sed
,awk
欢迎任何事情。优先考虑一个班轮。sed -n '/BEGIN/,/END/p' *
用于打印Search_pattern
"def"
和End_pattern
之间的行。但我无法在Start_pattern
和"def"
答案 0 :(得分:2)
使用gawk
,支持多字符RS
:
gawk 'BEGIN{RS=ORS="End_pattern"}/ef/' file
输出:
Start_pattern
abc
d
ef
ghij
klm
no End_pattern
Start_pattern
abc
def
hij End_pattern
说明:
# Split records based on the End_pattern
BEGIN{RS=ORS="End_pattern"}
# Print records that contain the search term
/ef/
顺便说一下,出于美观原因,您可能希望在输出结尾添加换行符:
gawk 'BEGIN{RS=ORS="End_pattern"}/ef/;END{printf "\n"}' file
PS:虽然上述解决方案仅适用于gawk
,但也可以使用与POSIX兼容的简单awk
脚本实现此目的,这意味着它适用于任何awk
:
awk '{b=b$0"\n"}/End_pattern/{if(b~/ef/){printf "%s",b};b=""}' file
说明:
# Append the current line plus a newline to b(uffer)
{b=b$0"\n"}
# Once End_pattern is found ...
/End_pattern/{
# Check if the buffer contains the search term
if(b~/ef/){
# Print the buffer when the term was found
printf "%s",b
}
# Clear the buffer
b=""
}
awk '{b=b$0"\n"}/End_pattern/{if(b~/ef/){printf "%s",b};b=""}' file
答案 1 :(得分:2)
为了完整起见,我在此处添加sed
解决方案:
sed -n '/Start_pattern/{:a;N;/End_Pattern/!ba;/ef/p}'
要理解这一点,您需要将标签和分支视为goto
statements
Start_pattern
,请执行{...}
a
:a
N
)End_Pattern
,请不要转到标签a
(!ba
)End_Pattern
后,执行最后一部分,声明如果完整记录包含ef
,请打印记录。答案 2 :(得分:1)
根据我在其他网站上的回答进行调整 - Get text between start pattern and end pattern based on pattern between start and end pattern
$ awk '/Start_pattern/{f=1; m=0; buf = $0; next}
/ef/ && f{m=1}
f{buf = buf ORS $0}
/End_pattern/ && f{f=0; if(m==1)print buf}
' ip.txt
Start_pattern
abc
d
ef
ghij
klm
no End_pattern
Start_pattern
abc
def
hij End_pattern
/Start_pattern/{f=1; m=0; buf = $0; next}
设置标志以指示阻止开始,清除匹配,初始化缓冲区并继续下一行/ef/ && f{m=1}
如果行包含ef
,请设置匹配。 f
用于避免在ef
Start_pattern...End_pattern
f{buf = buf ORS $0}
只要设置了标志,就会累积输入行/End_pattern/ && f{f=0; if(m==1)print buf}
在块结束时,如果找到匹配则打印缓冲区答案 3 :(得分:1)
$ cat tst.awk
/Start_pattern/ { fnd=1; buf="" }
fnd {
buf = buf $0 ORS
if (/End_pattern/) {
if (buf ~ /ef/) {
printf "%s", buf
}
fnd = 0
buf = ""
}
}
$ awk -f tst.awk file
Start_pattern
abc
d
ef
ghij
klm
no End_pattern
Start_pattern
abc
def
hij End_pattern