![Grep 两个文件并打印多次命中的行](https://linux22.com/image/180639/Grep%20%E4%B8%A4%E4%B8%AA%E6%96%87%E4%BB%B6%E5%B9%B6%E6%89%93%E5%8D%B0%E5%A4%9A%E6%AC%A1%E5%91%BD%E4%B8%AD%E7%9A%84%E8%A1%8C.png)
我有两个文件。
file1.txt
abc def ghi jkl mno pqr
file2.txt
abc ghi abc xyz xyz xyz mno jkl def stu
(列分隔符是制表符)
我正在尝试像这样grepfile1.txt
反对:file2.txt
grep -w -f file1.txt file2.txt
我得到以下输出:
abc ghi
abc xyz
mno jkl
def stu
但是,我想要的是输出两个都的第 1 列和第 2 列file2.txt
有命中file1.txt
,如下所示:
abc ghi
mno jkl
欢迎任何帮助。
谢谢。
担
答案1
将 的每个值保存file1.txt
在数组中a
。然后,解析file2.txt
并打印 中同时具有第一个和第二个字段的行a
。
awk 'NR==FNR{a[$0];next}$1 in a && $2 in a' file1.txt file2.txt
对于 中的任意数量的字段file2.txt
,循环遍历所有字段并执行检查。如果其中一个字段不在 中a
,则继续下一行,否则打印该行。
awk 'NR==FNR{a[$0];next}{for(i=1;i<=NF;i++){if(!($i in a)){next}}print}' file1.txt file2.txt
答案2
使用我们可以通过创建一个包含 元素的python
超集来接近 pbm 。b
file1.txt
然后,对于从中读取的每一行,file2.txt
我们检查从当前行形成的集合是否是超集 b 的子集。在这种情况下,我们打印 file2.txt 的当前行`
$ python3 -c 'import sys
f1, f2 = sys.argv[1:]
with open(f1) as fh1, open(f2) as fh2:
b = set([l.strip() for l in fh1])
print(*(l.rstrip() for l in fh2 if set(l.strip().split()).issubset(b)), sep="\n")
' file1.txt file2.txt
abc ghi
mno jkl
$ perl -lane '$. == 1 and
%h = map { /(.*)(\n)/ } <STDIN>;
print if ! grep { ! $h{$_} } @F;
' file2.txt < file1.txt
使用 sed,我们将 file1.txt 存储在保留空间中,然后对于从 File2.txt 读取的每一行,我们与当前行的所有元素的存在情况进行比较,并在找到所有元素时打印。
$ sed -Ee '
/\n/{h;d;}
/\s/!{H;d;}
G;h
s/\n.*//;s/\n//;x
:a
s/^\s?(\S+)((\s\S+)?\n.*\n\1(\n|$))/\2/
ta
s/^\n//;tb
D;:b;x
' file1.txt file2.txt
while IFS= read -r l <&3; do
read -r a b <<<"$l"
grep -qFe "$a" file1.txt &&
grep -qFe "$b" file1.txt &&
printf '<%s>\n' "$l"
done 3< file2.txt