首页 > 解决方案 > 如何过滤类似 grep 的搜索以要求 3 个字符串按给定的顺序和距离排列?

问题描述

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

第一个 2 总是一个接一个,第三个将是 #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”。它有效,但它并不漂亮。

标签: bashgrep

解决方案


根本不要grep在这里使用:awk是工作的正确工具。

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没有跟随的 newbar不会改变输出中显示的行号。
  • 我们初始化所有内容的原因0 - range是,这些值仍然是有效的整数(所以没有数学失败),而且baz在输入的第一range行中,a 没有看到值0as 意味着第 0 行有匹配项bar,并且因此在我们的 100 行搜索距离内。

推荐阅读