适用于重叠模式的 Grep

适用于重叠模式的 Grep

我想计算aa一个非常大的文件中重复模式的数量。所以我使用以下命令:

grep -o "aa" ./bwt/dblp.txt | wc -l

这是有效的,除非我有一个字符串,例如aaa,然后它仅将其匹配为 1 个模式。在我的用例中,我需要前 2 as 表示一个模式,但最后 2 as 是第二个模式(这意味着中间的afromaaa可以重复使用)。

我怎样才能实现这个目标?

请注意,该文件非常大,因此如果可能的话,“优化”方式会更好。无论如何,任何可行的解决方案显然都是受欢迎的。

答案1

为此,您需要 Perl 正则表达式。使用grep支持该标志的a -P

grep -oP '(?<=a)a' file | wc -l

这是一个积极的向后看。它匹配a前面有另一个 的单个a


如果您愿意perl(或者您grep不支持该-P标志):

perl -ne 'while(m/(?<=a)a/g){$a++}END{print "$a\n"}' file

例子:

$ cat file
aa
aaa
aaaa

第一行应该是 1 个匹配,第二行应该是两个,第三行应该是一棵树;总共6:

$ grep -oP '(?<=a)a' file | wc -l
6

答案2

您可以计算重复的字母对,例如aa数据文件中的示例big_file,如下所示:

tr -cs a '\012' <big_file | awk '/aa/{n += length - 1}; END {print n+0}'

该行可以这样解释

  • 更改tr任何不是换行符的字符序列a。这会将多次出现的 分成aa...不同的行
  • 计算awk非零行的长度。利用 N 个字符的序列包含 N-1 个重叠对的特性,可以将重叠对的数量相加,并在文件末尾生成总数

实际上,由于文件“非常大”,因此通过grep在管道中包含 a 会得到更好的响应,如下所示:

tr -cs a '\012' <big_file | grep aa | awk '{n += length - 1}; END {print n+0}'

答案3

由于某种原因,chaos 的答案在我的系统上没有输出任何内容(Debian 11.5,GNU grep 3.6)。以下是对我有用的方法,以防万一对其他人有用:

pcregrep -o1 -o2 '(\w)(?=(\w))' file

这在精神上与所提议的类似:如果第一个字母后跟捕获组 2 中的另一个字母,则使用捕获组 1 匹配第一个字母,只有后者使用正向前瞻进行匹配,以便我们之后仍然可以使用它。然后,使用-o1和显示这两个组-o2

这可以直接推广到长度为 的子序列n

pcregrep -o1 -o2 '(\w)(?=(\w{n-1}))' file

答案4

grep -ow aa ./bwt/dblp.txt | wc -l

相关内容