我有两个文件——file1 和 file2。
file1
包含(仅限文字):
ABC
YUI
GHJ
I8O
file2
包含多段内容:
dfghjo ABC kll
njjgg bla bla GHJ
njhjckhv chasjvackvh ..
ihbjhi hbhibb jh jbiibi
我正在使用下面的命令来获取包含单词 from 的匹配file1
行file2
:
grep -Ff file1 file2
(输出在file1
中找到单词的行file2
)
file1
我还需要中没有找到的单词file2
。
有人能帮助获得这个输出吗:
YUI
I8O
我正在寻找一个单行命令(通过,,grep
),因为我正在使用命令并且不能使用或循环。awk
sed
pssh
while
for
答案1
这里有一种方法awk
:
$ awk 'NR==FNR{a[$1]++; next}{for(i in a){if($0 ~ i){found[i]++}}}END{for(i in a){if(!found[i]){print i}}}' file1 file2
YUI
I8O
或者,更清晰一点的说法是:
$ awk 'NR==FNR{
a[$1]++;
next
}
{
for(i in a){
if($0 ~ i){
found[i]++
}
}
}
END{
for(i in a){
if(!found[i]){
print i
}
}
}' file1 file2
YUI
I8O
解释
NR==FNR
:NR
是当前行号,FNR
是当前文件的当前行号。处理多个文件时,只有在读取第一个文件时,这两个值才会相等。所以,这是“仅对第一个文件执行此操作”的简单说法。a[$1]++; next
:在读取第一个文件时,将每个单词(第一个也是唯一的字段)保存在数组中a
,然后跳到下一行。这next
还确保不会对第一个文件运行命令的其余部分。for(i in a){ if($0 ~ i){ found[i]++ } }
:对于第一个文件中找到的每个单词(数组的键a
),检查当前行是否与该单词匹配。如果匹配,则将该单词保存在数组中found
。对第二个输入文件的每一行都运行此操作。END{ }
:处理完所有输入文件后执行此操作。for(i in a){ if(!found[i]){ print i } }
:对于中的每个单词a
,如果该单词不在found
数组中,则打印该单词。
或者,您可以使用一些核心 Linux 实用程序:
$ grep -hoP '\w+' file1 file2 | sort | uniq -u | xargs -I{} grep {} file1
I8O
YUI
解释
$ grep -hoP '\w+' file1 file2
ABC
YUI
GHJ
I8O
dfghjo
ABC
kll
njjgg
bla
bla
GHJ
njhjckhv
chasjvackvh
ihbjhi
hbhibb
jh
jbiibi
这将打印每个文件中找到的所有单词。-o
标志表示“仅打印行的匹配部分”,-P
启用 Perl 兼容正则表达式 (PCRE),让我们使用它\w
来表示“任何单词字符”(字母、数字等_
)。
$ grep -hoP '\w+' file1 file2 | sort | uniq -u
chasjvackvh
dfghjo
hbhibb
I8O
ihbjhi
jbiibi
jh
kll
njhjckhv
njjgg
YUI
现在我们传递前一个命令的输出sort
并uniq -u
仅保留唯一的匹配:这些是仅出现在两个文件之一中的单词。
$ grep -hoP '\w+' file1 file2 | sort | uniq -u | xargs -I{} grep {} file1
I8O
YUI
最后,我们将这个唯一单词列表输入到 ,xargs
并将grep
每个单词放入 中file1
。只有出现在 中的唯一单词file1
才会被返回,file1
因此出现在 中的唯一单词不会出现在 中file2
。
答案2
尝试这个命令:
grep -oFf file1 file2 | grep -vFf - file1
首先使用 file1 作为 PATTERN,并仅获取 file2 中与 PATTERN 匹配的匹配行的部分,第一个命令为您提供:
ABC
GHJ
然后使用此输出作为输入文件 PATTERN 并在 file1 中搜索与 PATTERN 不匹配的行,您将得到:
YUI
I8O
已在 Red Hat Enterprise Linux ES 版本 4(Nahant Update 3)上测试
答案3
使用 Perl:
主要算法+Perl 等效算法:
slurp f2 // $f2 = `cat f2`
for all lines in f1 // perl -nle '....' f1
print if f2 does not have it // print if $f2 !~ /$_/
全部一起:
perl -nle 'BEGIN {$f2=`cat f2`}
print if $f2 !~ /$_/' f1