我目前正在处理大文件,寻找不匹配的模式。我正在使用 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
会这样做(模式ab
和ba
都会与 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 的答案慢,因为它寻找全部模式的出现次数。