我有这样的数据:
foo
...
bar
...
pattern
...
]
我需要首先匹配'模式'然后在' pattern'之前显示所有内容。达到' foo'以及模式下的所有内容到']'
grep应该这样做:
grep pattern -A grep foo -B grep ]
但是它没有。
答案不需要包含grep。 awk,sed和其他人欢迎。
答案 0 :(得分:1)
Soo ...你想在匹配foo
的东西和匹配]
的东西之间打印一个部分,如果它包含匹配pattern
的东西,那是正确的吗?然后
sed -n '/foo/ { :a; N; /\]/!ba /pattern/ p }' filename
sed代码的工作原理如下:
/foo/ { # if a line matches foo
:a # jump label
N # fetch the next line and append it to the pattern space
/\]/! ba # if the result does not match ] (that is, if the last fetched
# line does not contain something that matches ]), go back to :a
/pattern/ p # if in all these lines, there is something that matches the
# pattern, print them
}
使比赛在前面非贪婪 - 也就是说,如果在文件中
1
foo
2
foo
3
pattern
4
]
5
匹配应包括3
和4
但不包括2
,脚本可以像这样修改(或类似,具体取决于您要使用的模式):
sed -n '/foo/ { :a; N; /\n[^\n]*foo/ s/.*\n//; /\]/!ba /pattern/ p }' filename
如果该行中的某些内容与/\n[^\n]*foo/ s/.*\n//
匹配,则foo
将删除最后一次提取行之前的所有内容。
如果您的模式是线条模式(即,如果它们包含^
或$
),则需要对其进行修改。一旦模式空间中有多行,^
将匹配模式空间的开头和$
结尾,而不是一行。然后,您可以使用\n
来匹配行结尾。例如,如果您想要非正式地匹配foo
和]
之间的行,如果它们之间的行恰好是pattern
,则可以使用
sed -n '/^foo$/ { :a; N; /\nfoo$/ s/.*\n//; /\n\]$/!ba /\npattern\n/ p }' filename
答案 1 :(得分:1)
这是awk
awk '/foo/ {t=1} t {a[++b]=$0} /pattern/ {f=1} /^]/ {if (f) for (i=1;i<=b;i++) print a[i];delete a;b=t=f=0}' file
示例数据
cat file
foo
data
more
]
foo
...
bar
...
pattern
...
]
more
foo
here
yes
]
end
使用awk
awk '/foo/ {t=1} t {a[++b]=$0} /pattern/ {f=1} /^]/ {if (f) for (i=1;i<=b;i++) print a[i];delete a;b=t=f=0}'
foo
...
bar
...
pattern
...
]
更容易阅读:
awk '
/foo/ {t=1}
t {a[++b]=$0}
/pattern/ {f=1}
/^]/ {if (f)
for (i=1;i<=b;i++)
print a[i]
delete a
b=t=f=0
}
'
测试是否找到foo
,将t
设置为true
如果t
为真,则将所有行存储在数组a
中
如果找到pattern
,请设置标记f
如果找到]
,请测试标记f
是否为true,然后打印数组a
重置每个ting并重新开始。
答案 2 :(得分:0)
使用perl的单行:
perl -wln -0777 -e 'm/foo((?!foo).)*pattern[^\]]*\]/s and print $&;' [filename]
输入:
foo
foo
...
bar
...
pern
...
]
]
foo
...
pattern
]
]
foo
]
输出:
perl -wln -0777 -e 'm/foo((?!foo).)*pattern[^\]]*\]/s and print $&;' testtest
foo
...
pattern
]
一些关键点:
m/.../s
的单行模式,请参阅this post:foo((?!foo).)*pattern[^\]]*\]
foo
匹配第一个foo ((?!foo).)*
使用negative lookahead foo
pattern
匹配模式[^\]]*\]
以下部分不应包含]
,以]