在模式匹配之后显示n行和m行是n& m本身就是模式匹配

时间:2015-02-03 16:59:25

标签: awk sed grep

我有这样的数据:

foo
...
bar
...
pattern
...
]

我需要首先匹配'模式'然后在' pattern'之前显示所有内容。达到' foo'以及模式下的所有内容到']'

grep应该这样做:

grep pattern -A grep foo -B grep ]

但是它没有。

答案不需要包含grep。 awk,sed和其他人欢迎。

3 个答案:

答案 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

匹配应包括34但不包括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
]

analysis on regex101

一些关键点:

  1. 在perl中启用m/.../s的单行模式,请参阅this post
  2. 正则表达式foo((?!foo).)*pattern[^\]]*\]
    • foo匹配第一个foo
    • ((?!foo).)*使用negative lookahead
    • 避免在匹配的部分中匹配foo
    • pattern匹配模式
    • [^\]]*\]以下部分不应包含],以]
    • 结尾