我有一个文件 source.txt
,其中包含两列由空格分隔的字符串。
foo bar
foo baz
goo gaa
此外,还有另一个文件 pattern.txt
,它是应用作模式源的字符串列表(每行 1 个)。这可能看起来像
foo
bar
goo
目标是仅从模式文件中提取包含两个字符串的行。
重复是可以的(例如 foo foo
是有效的)。
所以这里期望的输出是
foo bar
我设法使用 grep
从模式文件中提取至少包含一个术语的行:
grep -wFf pattern.txt source.txt
上面的命令将返回 source.txt
中的所有行,因为每一行中至少存在 pattern.txt
中的一个术语。我使用管道 grep
命令(在仅考虑两个搜索词的相关问题中显示)的方法尚未成功。
grep
不是强制性的。 awk
、sed
、perl
也可以工作。我有一个 Python 解决方案,但它非常慢(“极快”)。
谢谢!
对答案的回应
我的 Python 解决方案如下所示:
import sys
f_pattern = sys.argv[1]
f_source = sys.argv[2]
with open(f_pattern, "r", encoding="utf-8") as fp:
pattern = set(fp.read().split("\n"))
with open(f_source, "r", encoding="utf-8") as fp:
for line in fp:
w1, w2 = line.strip("\n").split(" ")
if w1 in pattern and w2 in pattern:
print(line, end="") # \n still present in line string
事实上,与某些答案相比,这并没有那么糟糕(从时间角度来看)。
(我的)Python
time python matcher.py pattern.txt source.txt
>> 158,12s user 1,82s system 99% cpu 2:40,08 total
awk,作者:@Avinash Chandravansi
time awk -F' ' 'FNR==NR {arr [$0];next} $2 in arr' pattern.txt source.txt
>> 106,72s user 5,69s system 99% cpu 1:52,88 total
还不太确定,但我认为这给出了错误的结果。
awk,作者:@KamilCuk
time awk 'NR==FNR{a[$0];next} {cnt=0; for (k in a) { cnt += $0~k; if (cnt >= 2){ print; break; }}}' pattern.txt source.txt
>> Unclear, more then 20 minutes. Ctrl+C
awk,作者:@Fravadona
time awk 'FNR==NR {patterns[$0]; next}($1 in patterns) && ($2 in patterns)' pattern.txt source.txt
>> 95,45s user 2,46s system 99% cpu 1:38,03 total
^-- 这似乎是公认的答案(对我来说)。
最佳答案
您正在使用 grep -F
所以我猜“模式”不是正则表达式。现在,如果您正在寻找匹配完整字符串(而不是子字符串),那么您可以执行以下操作:
awk '
FNR == NR { patterns[$0]; next }
($1 in patterns) && ($2 in patterns)
' pattern.txt source.txt
关于unix - 包含另一个文件中的两个字符串的匹配行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75464230/