2つのテキストファイルを検索し、そのうちの1つだけにある各ファイルの行をファイルとして印刷したいと思います。
たとえば、LIST-1.txt には以下が含まれます。
apples
dogs
paintings
mom
dad
don
LIST-2.txt には以下が含まれます。
apples
don
dad
mom
cats
私は出力を(どんな順序でも)ほしいと思います:
dogs
paintings
cats
私はこれを試しました:
cat list-1.txt | while read line || [[ -n $line ]];
do
grep -v $line list-2.txt
done
どんな提案がありますか?
ベストアンサー1
ループの問題は、反復ごとに次のようになることです。最初のファイルの現在の行と他の2番目のファイルのすべての行。
ループの変形は、次の2つのコマンドの出力を接続することです。
grep -v -xF -f LIST-1.txt LIST-2.txt
grep -v -xF -f LIST-2.txt LIST-1.txt
1つ目は、任意の行とまったく一致しないすべての行をgrep
取得し、2つ目は2つのファイルに対して同じことを行います。これは実際にあなたの質問に記載されている結果を提供します。 (私は見たLIST-2.txt
LIST-1.txt
grep
ジェフはすでにこれを言及しています。したがって、このアプローチが気に入った場合は、私の答えの代わりに彼の答えに投票してください。 )
ファイルのいずれかをクエリ文字列としてメモリに読み込む必要があり、少しエレガントではないと見なすことができます。また、正しい結果が得られない状況についても、実際に考えたことはありません。
個人的に私は選択します。
$ join -v 1 -v 2 <( sort LIST-1.txt ) <( sort LIST-2.txt )
cats
dogs
paintings
これにより、ファイル間のリレーショナルJOIN操作が実行されます。通常、これは両方のファイルに存在する項目を返します(内部結合)、ここでは-v 1 -v 2
すべての項目を確認するように要求します。いいえすべてのファイルで一致します。
このjoin
ユーティリティにはソートされた入力が必要です(一度に各ファイルの1行だけをメモリに保存できます)。したがって、両方のファイルを並べ替え、join
別々のプロセスの交換を通じて提供します。
プロセス置換を持たないシェルでは、以下を呼び出す前にファイルのソートされたコピーを作成する必要がありますjoin
。
sort -o LIST-1.txt.sorted LIST-1.txt &&
sort -o LIST-2.txt.sorted LIST-2.txt &&
join -v 1 -v 2 LIST-[12].txt.sorted
rm -f LIST-[12].txt.sorted