如何过滤类似grep的搜索,以要求3个字符串的给定顺序和距离?

时间:2019-02-19 12:25:01

标签: bash grep

我有一个文件,我想从中查看在有限的行数范围内是否存在3个特定的字符串。

前2个将始终紧挨着,第3个将是#2之后的X行。 #3也可以不止一次地存在,但我只想要第一个。

例如

nope    
nope
foo    
bar    
nope
nope
nope
nope
baz
nope
baz (ignore this one)

如果foo和bar紧挨着存在并且baz在100行之内,我就“赢”。我如何轻松实现这一目标?

现在,我将其分解为许多小步骤,只要找到“ foo”,就使用grep -A100(和其他grep东西)创建临时文件,然后检查它们的“ bar”和“ baz”。可以,但是不漂亮。

1 个答案:

答案 0 :(得分:1)

完全不要在这里使用grepawk是完成这项工作的正确工具。

awk -v range=100 '
BEGIN { matchedFoo = seenFoo = seenBar = (0 - range) }
/foo/ { seenFoo=NR }
/bar/ { if (seenFoo == NR-1) { seenBar=NR; matchedFoo=seenFoo; } }
/baz/ && (seenBar > (NR - range)) {
  print("Matched foo@" matchedFoo ", bar@" seenBar ", baz@" NR);
  exit(0);
}
'

...发出,并带有您的示例输入:

Matched foo@3, bar@4, baz@9

...正确发出所需实例的行号。 (当然,如果需要,您可以存储除数字以外的完整字符串)。


关于逻辑的简短说明:

  • 我们将变量seenFoomatchedFoo分开的原因是,没有后跟foo的新bar不会更改输出中显示的行号。 / li>
  • 我们将所有内容都初始化为0 - range的原因是,这些值仍然是有效的整数(因此没有数学失败),而且输入的前baz行中的range也不没有看到0的值,这意味着第0行有bar的匹配项,因此在我们的100行搜索距离之内。