web-dev-qa-db-ja.com

一致しない文字列をfile1からfile2に取得

File1とfile2の2つのファイルがあります。

file1次を含む(単語のみ):

ABC 
YUI 
GHJ 
I8O

file2には多くの段落が含まれています:

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

以下のコマンドを使用して、file1file2からWordを含む一致する行を取得します。

grep -Ff file1 file2 

file1の単語がfile2で見つかった行の出力を提供します)

file1にはないfile2の単語も必要です。

誰でもこの出力を得るのを助けることができます:

YUI 
I8O

grepコマンドを使用していて、awkまたはsedループを使用できないため、(psshwhileforを介して)1つのライナーコマンドを探しています。

1
Sin15

awkの1つの方法を次に示します。

_$ 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は現在のファイルの現在の行番号です。複数のファイルを処理する場合、最初のファイルを読み取っている間だけ、2つは等しくなります。したがって、これは「これを最初のファイルに対してのみ行う」という簡単な方法です。
  • _a[$1]++; next_:最初のファイルの読み取り中に、各Word(最初で唯一のフィールド)を配列aに保存し、次の行にスキップします。 nextは、コマンドの残りの部分が最初のファイルに対して実行されないようにします。
  • for(i in a){ if($0 ~ i){ found[i]++ } }:最初のファイル(配列aのキー)にある各単語について、現在の行がその単語と一致するかどうかを確認します。含まれている場合は、Wordをfound配列に保存します。これは、2番目の入力ファイルの各行に対して実行されます。
  • _END{ }_:これは、すべての入力ファイルを処理した後で行います。
  • for(i in a){ if(!found[i]){ print i } }aの各単語について、Wordがfound配列にもない場合は、そのWordを印刷します。

あるいは、いくつかのコア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_は_\w_を使用して「任意のWord文字」を意味するPerl互換正規表現(PCRE)を有効にします(文字、数字、___)。

_$ grep -hoP '\w+' file1 file2 | sort | uniq -u
chasjvackvh
dfghjo
hbhibb
I8O
ihbjhi
jbiibi
jh
kll
njhjckhv
njjgg
YUI
_

次に、前のコマンドの出力をsortおよび_uniq -u_を介して渡し、一意の一致のみを保持します。これらは、2つのファイルのいずれかにのみ存在する単語です。

_$ grep -hoP '\w+' file1 file2 | sort | uniq -u | xargs -I{} grep {} file1
I8O
YUI 
_

最後に、この一意の単語のリストをxargsにフィードし、_file1_にそれらをそれぞれgrepに入れます。 _file1_に存在する一意の単語のみが返されるため、_file1_に存在する一意の単語は_file2_には存在しません。

1
terdon

このコマンドを試してください:

grep -oFf file1 file2 | grep -vFf - file1

最初にfile1をPATTERNとして使用し、file2のPATTERNと一致する一致する行の一部のみを取得する場合、最初のコマンドで次のようになります。

ABC
GHJ

次に、この出力を入力ファイルPATTERNおよびPATTERNと一致しないfile1の検索行として使用すると、次の結果が得られます。

YUI
I8O

Red Hat Enterprise Linux ESリリース4(Nahant Update 3)でテスト済み

0
Lety

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
0
user216043