2つ以上のファイルから共通の行を出力できるUNIXコマンドを一度見つけたと確信していますが、その名前を知っている人はいますか? diff
よりもずっと簡単でした。
探しているコマンドは comm
です。例えば:-
comm -12 1.sorted.txt 2.sorted.txt
ここに:
-1:列1を抑制します(1.sorted.txtに固有の行)
-2:列2(2.sorted.txtに固有の行)を抑制
commコマンドをunsortedファイルに簡単に適用するには、Bashの-を使用します プロセス置換 :
$ bash --version
GNU bash, version 3.2.51(1)-release
Copyright (C) 2007 Free Software Foundation, Inc.
$ cat > abc
123
567
132
$ cat > def
132
777
321
したがって、ファイルabcとdefには1行が共通しており、「132」が含まれています。ソートされていないファイルでcommを使用する:
$ comm abc def
123
132
567
132
777
321
$ comm -12 abc def # No output! The common line is not found
$
最後の行は出力を生成せず、共通行は検出されませんでした。
次に、ソートされたファイルでcommを使用し、プロセス置換でファイルをソートします。
$ comm <( sort abc ) <( sort def )
123
132
321
567
777
$ comm -12 <( sort abc ) <( sort def )
132
これで132行ができました!
Perlのワンライナーを補完するために、同等のawk
を次に示します。
awk 'NR==FNR{arr[$0];next} $0 in arr' file1 file2
これにより、file1
からすべての行が配列arr[]
に読み込まれ、file2
の各行が既に配列内に存在するかどうかが確認されます(つまり、file1
)。見つかった行は、file2
に表示される順序で印刷されます。比較in arr
はfile2
からの行全体を配列のインデックスとして使用するため、行全体の完全一致のみを報告することに注意してください。
多分あなたはcomm
を意味しますか?
ソートされたファイルFILE1とFILE2を1行ずつ比較します。
オプションなしで、3列の出力を生成します。列1にはFILE1に固有の行が含まれ、列2にはFILE2に固有の行が含まれ、列3には両方のファイルに共通の行が含まれます。
これらの情報を見つける秘secretは、情報ページです。 GNUプログラムの場合、それらはマンページよりもはるかに詳細です。 info coreutils
を試してください。小さな便利なユーティリティがすべてリストされます。
ながら
grep -v -f 1.txt 2.txt > 3.txt
2つのファイル(1.txtではなく2.txtにあるファイル)の違いを示します。
grep -f 1.txt 2.txt > 3.txt
すべての一般的な行を収集します。これにより、問題を簡単に解決できます。ファイルをソートした場合は、comm
を使用する必要があります。よろしく!
2つのファイルがまだソートされていない場合は、次を使用できます。
comm -12 <(sort a.txt) <(sort b.txt)
comm: file 2 is not in sorted order
を実行するときにエラーメッセージcomm -12 a.txt b.txt
を回避して動作します。
Perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2
Linuxの限定バージョン(私が取り組んでいたQNAP(nas)など):
grep -f file1 file2
は@ChristopherSchultzが言ったようにいくつかの問題を引き起こす可能性があり、grep -F -f file1 file2
の使用は本当に遅かった(5分以上-終了しない-20MBを超えるファイルで以下の方法で2〜3秒以上)だからここに私がやったことがあります:
sort file1 > file1.sorted
sort file2 > file2.sorted
diff file1.sorted file2.sorted | grep "<" | sed 's/^< *//' > files.diff
diff file1.sorted files.diff | grep "<" | sed 's/^< *//' > files.same.sorted
files.same.sorted
が元のものと同じ順序である場合、file1と同じ順序でこの行を追加します。
awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file1 > files.same
または、file2と同じ順序の場合:
awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file2 > files.same
誰かがまだ複数のファイルでこれを行う方法を探している場合の参考のために、リンクされた答えを参照してください 多くのファイルで一致する行を見つける
これらの2つの答え( ans1 および ans2 )を組み合わせると、ファイルを並べ替えなくても必要な結果が得られると思います。
#!/bin/bash
ans="matching_lines"
for file1 in *
do
for file2 in *
do
if [ "$file1" != "$ans" ] && [ "$file2" != "$ans" ] && [ "$file1" != "$file2" ] ; then
echo "Comparing: $file1 $file2 ..." >> $ans
Perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' $file1 $file2 >> $ans
fi
done
done
単に保存し、実行権限(chmod +x compareFiles.sh
)を付与して実行します。現在の作業ディレクトリに存在するすべてのファイルを取得し、「matching_lines」ファイルに結果を残して、すべて対すべての比較を行います。
改善すべき点: