web-dev-qa-db-ja.com

2つのファイルに共通する行を検索するUnixコマンド

2つ以上のファイルから共通の行を出力できるUNIXコマンドを一度見つけたと確信していますが、その名前を知っている人はいますか? diffよりもずっと簡単でした。

167
too much php

探しているコマンドは comm です。例えば:-

comm -12 1.sorted.txt 2.sorted.txt

ここに:

-1:列1を抑制します(1.sorted.txtに固有の行)

-2:列2(2.sorted.txtに固有の行)を抑制

200

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行ができました!

58
Stephan Wehner

Perlのワンライナーを補完するために、同等のawkを次に示します。

awk 'NR==FNR{arr[$0];next} $0 in arr' file1 file2

これにより、file1からすべての行が配列arr[]に読み込まれ、file2の各行が既に配列内に存在するかどうかが確認されます(つまり、file1)。見つかった行は、file2に表示される順序で印刷されます。比較in arrfile2からの行全体を配列のインデックスとして使用するため、行全体の完全一致のみを報告することに注意してください。

25
Tatjana Heuser

多分あなたは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を使用する必要があります。よろしく!

18
ferdy

2つのファイルがまだソートされていない場合は、次を使用できます。

comm -12 <(sort a.txt) <(sort b.txt)

comm: file 2 is not in sorted orderを実行するときにエラーメッセージcomm -12 a.txt b.txtを回避して動作します。

8
Basj
Perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2
8
user2592005
awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2
5
R S John

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
3
Master DJon

誰かがまだ複数のファイルでこれを行う方法を探している場合の参考のために、リンクされた答えを参照してください 多くのファイルで一致する行を見つける


これらの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」ファイルに結果を残して、すべて対すべての比較を行います。

改善すべき点:

  • ディレクトリをスキップ
  • すべてのファイルを2回比較しないでください(file1対file2およびfile2対file1)。
  • 一致する文字列の横に行番号を追加する場合があります
2
akarpovsky