回答:
あなたの目標が一般的なまたは珍しい行を見つけるcomm
ことであるなら、ここで私の頼りになるコマンドでしょう。
2つのファイルを比較し、ファイル1に固有の行を3列で、ファイル2に固有の行と、両方のファイルに表示される行をそれぞれ示します。フラグを渡して、この出力を抑制することもできます。たとえばcomm -1 file1 file2
、file1に固有の最初の列を抑制します。comm -12 file1 file2
両方のファイルにあるものだけを表示します。
注意点が1つあります。入力をソートする必要があります。これを回避できます。
これにより、mnoにないすべてのabcが表示されます。
comm -23 <(sort abc.txt) <(sort mno.txt)
そして、それをパイプしてwc -l
、カウントを取得できます。
私が行く理由comm
は、いったんファイルがソートされると、並列比較は計算上非常に簡単だからです。あなたがこれらの何百万もの問題を扱っているなら、それは違いを生むでしょう。
これは、いくつかのモックファイルで実証できます。私はかなり高速なコンピューターを持っているので、アプローチの違いを示すために、かなり巨大なサンプルセットが必要です。ファイルごとに1000万の10文字の文字列に移動しました。
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > abc.txt
$ cat /dev/urandom | tr -dc '0-9' | fold -w 10 | head -10000000 > mno.txt
$ time comm -23 <(sort abc.txt) <(sort mno.txt) | wc -l
... 0m10.653s
$ time grep -Fcxv -f abc.txt mno.txt
... 0m23.920s
$ time grep -Fcwv -f abc.txt mno.txt
... 0m40.313s
$ time awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt | wc -l
... 0m12.161s
並べ替えは、私の時間のほとんどがかかります。abc.txtが静的なふりをする場合は、それを事前に並べ替えることができるため、将来の比較がはるかに速くなります。
$ sort abc.txt abc-sorted.txt
$ time comm -23 abc-sorted.txt <(sort mno.txt) | wc -l
... 0m7.426s
あなたはこれらを見て、数秒は無関係であると考えるかもしれませんが、これらがハイエンドマシンで実行されていることを強調しなければなりません。(例えば)Raspberry Pi 3でこれを実行したい場合は、ターンアラウンドがはるかに遅くなり、違いが実際に問題になるほど大きくなります。
リストを取得するには:
grep -Fwf abc.txt mno.txt
それはあなたに似たものを与えます:
abcd
abcd
zef
一意のリストを取得したい場合は、次のように使用します。
grep -Fwf abc.txt mno.txt | sort | uniq
カウントを取得するには:
grep -Fcwv -f abc.txt mno.txt
-F
つまり、PATTERNを正規表現ではなく固定文字列のリストとして解釈します。-f
になるパターンをFILEから取得しますabc.txt
。mno.txt
はパターンを調べます-c
一致の数を数える-w
「単語全体」のみを検索します。一致する部分文字列は、行の先頭か、単語の構成文字の前に置く必要があります。同様に、行の終わりか、単語以外の構成文字が後に続く必要があります。単語構成文字は、文字、数字、およびアンダースコアです。-v
検索を逆にしますfgrep
、egrep
交互には、おそらくの賛成で(廃止されgrep -F
、grep -E
私は誰もが彼らがこれまで離れて行くだろうと考えているか分からないが-
-x
時に使用する必要はあります-F
か?
abcdef
一致または非一致としてカウントする必要がありますabcd
か?
awkを使用して、最初にパターンファイル、次にチェックするファイルの2つのファイルを渡すことで、ジョブを実行できます。最初のファイルを読み込んでいるとき、それがわかっているのでNR==FNR
、そのときに行を配列に読み込むことができます。そのNR!=FNR
ような行の配列が設定されているかどうかを確認すると。
$ cat abc.txt
abcd
xyz
pqrs
$ cat mno.txt
zzon
xyz
mkno
abcd
$ awk 'NR==FNR{a[$0]++};NR!=FNR && a[$0]' abc.txt mno.txt
xyz
abcd
逆に、パターンを無効にして、含まれていない行を印刷できます abc.txt
$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt mno.txt
zzon
mkno
私たちは人々の数を印刷したい場合は、私たちは採用することができるsort
とwc
:
$ awk 'NR==FNR{a[$0]++};NR!=FNR && ! a[$0]' abc.txt mno.txt | sort -u | wc -l
2
abc.txt
- mno.txt
です{xyz, pqrs}
。
どちらかの単語リストがソートされていない場合、効率的なセットデータ構造を使用して一般的な単語を覚える方が高速です。
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as minuend_file:
minuend = frozenset(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
subtrahend = frozenset(map(str.rstrip, subtrahend_file))
difference = minuend - subtrahend
#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference
使用法:
python3 set-difference.py abc.txt mno.txt
中間ストレージとランタイムのために少しメモリを節約したい場合は、これを少し理解しにくいプログラムを使用できます。
#!/usr/bin/env python3
import sys
with open(sys.argv[1]) as minuend_file:
minuend = set(map(str.rstrip, minuend_file))
with open(sys.argv[2]) as subtrahend_file:
subtrahend = map(str.rstrip, subtrahend_file)
minuend.difference_update(subtrahend)
difference = minuend
del minuend
#print(*difference, sep='\n') # This prints the content of the set difference
print(len(difference)) # This prints the magnitude of the set difference
与えられabc.txt
、mno.txt
1つのmioで並べ替えられていない、それぞれ10個のランダムなASCII数字文字(未設定のOliの回答を参照):
$ time python3 set-difference.py abc.txt mno.txt
user 0m10.453s
対
$ export LC_COLLATE=C
$ time sort abc.txt > abc_sorted.txt
user 0m10.652s
$ time sort mno.txt > mno_sorted.txt
user 0m10.767s
$ time comm -23 abc_sorted.txt mno_sorted.txt | wc -l
9989882
user 0m1.600s
合計:23秒
grep -cxvFf abc.txt mno.txt
?