相当于 grep 字符串匹配 sed 和 awk

相当于 grep 字符串匹配 sed 和 awk

我目前正在处理大文件,寻找不匹配的模式。我正在使用 grep 来实现这一点。由于某种原因,grep 忽略/排除一些潜在的不匹配模式。模式文件和字符串文件均由十六进制字符组成。大约有 200k 个模式,每个模式的长度在 12 到 500 个字符之间,还有 13k 个字符串,每个字符串的长度为 2,880,560 个字符。我正在使用以下命令:

grep -oFf patterns.txt large_strings.txt | grep -vFf - patterns.txt > unmatched_patterns.txt

上面的命令首先提取所有匹配的模式,然后将匹配的模式中不匹配的模式保存到文本文件中。是否有等效的 sed 或 awk 命令来模仿此任务?我使用两台不同的机器(我的个人机器和集群)尝试了上面提到的 grep 命令,结果是相同的。

我运行getconf ARG_MAX并获得了集群的以下输出:

4611686018427387903

一些不匹配模式的示例如下:

fffbfefffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffffffffefffffefffffefffffefffffefffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffff
1d2a0e1d2a101c290f1b280e1a270d18250b17240a17230b16220a16220a15210915210916220a16220c19220d1b230e1b230e1b230e1c240d1c240d1c240d1c240d1b250c1c260d1c26
fefffffefffffffffffffffffffdfffffffffffdfeff

由两个字符串组成的大字符串的示例文件可以在下面的链接中找到: https://www.mediafire.com/file/b1plp74uztkicyr/large_strings.txt/file

答案1

使用awk,将所有模式作为键读入关联数组。然后逐行检查数据文件中的行,并针对每一行测试每个剩余的模式。如果模式匹配,则将其从关联数组中删除。

最后,输出未匹配的模式。

NR == FNR { pat[$0] = 1; next }

{
    for (p in pat)
        if (index($0,p) != 0)
            delete pat[p]
}

END {
    for (p in pat)
        print p
}

您可以将其保存到文件中,例如script.awk,然后运行

awk -f script.awk patterns.txt large_strings.txt >unmatched_patterns.txt

这将使用index(),而不是正则表达式匹配(就像使用grep -F)来执行字符串比较,但可能会在数据中的重叠位置匹配多个模式字符串,我认为不grep会这样做(模式abba都会与 data 匹配aba)。

对虚拟数据进行测试:

$ cat patterns.txt
a
b
c
d
$ cat strings.txt
abba
bull
cooler
$ awk -f script.awk patterns.txt strings.txt
d

d(在文件中找不到该字符串strings.txt。)

答案2

使用 GNU grep,我会这样做:

(
  export LC_ALL=C
  sort -uo patterns.txt patterns.txt # if not already uniqued and sorted in the C locale
  grep -oFf patterns.txt large_strings.txt |
    sort -u |
    comm -13 - patterns.txt > unmatched_patterns
)

理论上,它应该比 @Kusalananda 的答案慢,因为它寻找全部模式的出现次数。

相关内容