Awk 显示模式匹配之前的n行和之后的m行是n&;m本身就是模式匹配

Awk 显示模式匹配之前的n行和之后的m行是n&;m本身就是模式匹配,awk,sed,grep,Awk,Sed,Grep,我有这样的数据: foo ... bar ... pattern ... ] 我需要首先匹配“模式”,然后显示“模式”之前到“foo”的所有内容,以及模式之后到“]”的所有内容 grep应该这样做: grep pattern -A grep foo -B grep ] 但遗憾的是,事实并非如此 答案不需要包括grep。 欢迎awk、sed和其他人。所以…您想在匹配foo的内容和匹配]的内容之间打印一个部分,如果它包含匹配模式的内容,是否正确?然后 sed -n '/foo/ { :a; N;

我有这样的数据:

foo
...
bar
...
pattern
...
]
我需要首先匹配“模式”,然后显示“模式”之前到“foo”的所有内容,以及模式之后到“]”的所有内容

grep应该这样做:

grep pattern -A grep foo -B grep ]
但遗憾的是,事实并非如此

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

所以…您想在匹配
foo
的内容和匹配
]
的内容之间打印一个部分,如果它包含匹配
模式的内容,是否正确?然后

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
,脚本可以这样修改(或类似修改,取决于您想要使用的模式):

其中,
/\n[^\n]*foo/s/*\n/
将删除最后一个提取行之前的所有内容,如果该行中的内容与
foo
匹配

如果您的模式是线型模式(即,如果它们包含
^
$
),则需要对其进行修改。一旦图案空间中有多行,
^
将匹配图案空间的开头,
$
将匹配图案空间的结尾,而不是一行。然后可以使用
\n
匹配行尾。例如,如果您想在完全为
foo
的行和完全为
模式的行之间进行非贪婪匹配,则可以使用

sed -n '/^foo$/ { :a; N; /\nfoo$/ s/.*\n//; /\n\]$/!ba /\npattern\n/ p }' filename

这是一个
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
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测试

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
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使用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
]

一些要点:

  • 在perl中使用
    m/../s
    打开单行模式请参阅:
  • 正则表达式
    foo((?!foo)。)*模式[^\]*\]
    • foo
      匹配第一个foo
    • ((?!foo)。*)*
      避免在匹配零件中使用
    • 模式
      匹配模式
    • [^\]*\]
      以下部分不应包含
      ]
      并以
      ]

  • 那么,您想要的确切输出是什么?您的示例输入不充分。显示示例输入,其中包括范围重叠和/或文件开始/结束出现在预期范围之前/之后的情况,等等,以及相关的输出。还要定义“模式”(ais是stginr、BRE、ERE还是其他什么?),并显示您是否想要完整的输入“word”或整行仅用于匹配或部分匹配。否则,我们只是猜测您几乎所有的需求。
    perl -wln -0777 -e 'm/foo((?!foo).)*pattern[^\]]*\]/s and print $&;' testtest
    foo
    ... 
    pattern
    ]