获取从 file1 到 file2 的非匹配字符串

获取从 file1 到 file2 的非匹配字符串

我有两个文件——file1 和 file2。

file1包含(仅限文字):

ABC 
YUI 
GHJ 
I8O

file2包含多段内容:

dfghjo ABC kll 
njjgg bla bla GHJ 
njhjckhv chasjvackvh .. 
ihbjhi hbhibb jh jbiibi 

我正在使用下面的命令来获取包含单词 from 的匹配file1file2

grep -Ff file1 file2 

(输出在file1中找到单词的行file2

file1我还需要中没有找到的单词file2

有人能帮助获得这个输出吗:

YUI 
I8O

我正在寻找一个单行命令(通过,,grep),因为我正在使用命令并且不能使用或循环。awksedpsshwhilefor

答案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

现在我们传递前一个命令的输出sortuniq -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

相关内容