如何提取包含pattern.txt中两个字符串的source.txt行?
需求与高效解决方案
需求说明
我有一个source.txt文件,内容为空格分隔的两列字符串:
foo bar foo baz goo gaa
另有一个pattern.txt文件,每行一个字符串作为匹配源:
foo bar goo
目标:仅提取source.txt中两列字符串都存在于pattern.txt中的行,重复字符串(如foo foo)也视为有效。预期输出为:
foo bar
我已能用grep提取包含pattern.txt中至少一个字符串的行:
grep -wFf pattern.txt source.txt
但该命令会返回source.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
性能测试结果:
time python matcher.py pattern.txt source.txt >> 158,12s user 1,82s system 99% cpu 2:40,08 total
@Avinash Chandravansi的awk方案
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
该方案返回结果疑似不正确。
@KamilCuk的awk方案
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
运行时间过长,已手动终止。
@Fravadona的awk方案
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
该方案为最优解。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

