6つのファイル間の共通点を見つける

6つのファイル間の共通点を見つける

Linuxシステムには6つの.txtファイルがあり、各ファイルには約1700行があります。この6つのファイルのうち6つ、次に5/6、4/6、3/6、最後の6つのファイルに共通の行を見たいと思います。次のコードを試してみました。

comm -12 2.txt 3.txt | comm -12 - 4.txt | comm -12 - 5.txt | comm -12 - 6.txt | comm -12 - 7.txt

しかし、結果は不完全で互換性がないことがわかりました。その後、いくつかの調査を行い、次のコードを試しました。

awk 'NR==FNR { lines[$0]=1; next } $0 in lines' 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt

しかし、それも動作しません。

私はUbuntuに初めて触れたので、非常に基本的なものだけを知っています。私を助けてくれてありがとう。よろしくお願いします。

編集1:@terdonの提案に従って、次のコードも試しました。

sort file1 file2 file3 file4 file5 file6 | uniq -c

それは私に次のような結果を与えます:

3 VAL455-Main VAL451-Main 
1 VAL455-Main VAL451-Main 
3 VAL463-Main ALA459-Main 
1 VAL463-Main ALA459-Main 
3 VAL468-Main LEU466-Main 
1 VAL468-Main LEU466-Main 
3 VAL468-Main LYS464-Main 

「VAL468-Main LEU466-Main」を見てみましょう。ご覧のとおり、出力には2つの異なる結果があります。これは、対応する行が3つのファイルに同時に存在し、1つのファイルにのみ存在することを意味します。ただし、この行はすべてのファイルに表示されます。

だから我々はまだ解決策を見つけることができませんでした。

編集2:@FelixJNのおかげで問題の原因を見つけました。同様の状況に直面している場合は、彼の答えを読んでください。 :)

ベストアンサー1

一緒にawk次のことができます。

#skip if multiple appearance in one file
{if ( seenin[$0] ~ FILENAME ) {next}}
#add filename to list of files the line has been seen in, increase seen counter
{seenin[$0]=seenin[$0]" "FILENAME ; nseen[$0]++}

#print
END {for (line in nseen) { if (nseen[line]>1) {
   printf "%s \"%s\" %s %d %s %s\n",
     "line",line,"seen in",nseen[line],"files:",seenin[line]} } }

制限事項:すべての行がRAMに保持されるため、メモリです。

発生回数に基づいてソートするには、それに応じて印刷コマンドを調整する必要があります(例:値によるソート)nseen。簡単ですgawkENDブロックに次のbefore -loopを追加しますfor

PROCINFO["sorted_in"]="@val_num_desc"

入力ファイル:

$ cat file1
a
a
b
b
c
d
e

$ cat file2
c
c
x
z
e
y
z
f

$ cat file3
f
i
a
c
z
i
k

出力(gawk配列巡回機能付きPROCINFO

$awk -f compare_lines_multifiles.awk file1 file2 file3
line "c" seen in 3 files:  file1 file2 file3
line "z" seen in 2 files:  file2 file3
line "a" seen in 2 files:  file1 file3
line "e" seen in 2 files:  file1 file2
line "f" seen in 2 files:  file2 file3

編集する:

提供されたファイルはMSDOS形式です。変換して

 dos2unix file1.txt file2.txt ....

またはでレコード区切り記号を調整しますawk。コードの最初の項目として次を追加します。

 BEGIN { RS="\r\n" }

編集2:ファイルに不規則な区切り記号があります。問題は、 と がa<tab>ba<tab>b<tab>の行で処理されるのに対し、同じと考えることができるということです。

ファイルごとに2つの関心フィールドがある特別な場合は、行全体ではなく2つのフィールドの内容を比較することをお勧めします。 MSDOS 形式も​​考慮してください。

BEGIN { RS="\r\n" }
#skip if multiple appearance in one file
{if ( seenin[$1"\t"$2] ~ FILENAME ) {next}}
#add filename to list of files the line has been seen in, increase seen counter
{seenin[$1"\t"$2]=seenin[$1"\t"$2]" "FILENAME ; nseen[$1"\t"$2]++}

#print
END {for (line in nseen) { if (nseen[line]>1) {
   printf "%s \"%s\" %s %d %s %s\n",
     "line",line,"seen in",nseen[line],"files:",seenin[line]} } }

結局、6つのファイルはすべて重複していました。タブ区切り記号がある2つのフィールドに焦点を合わせ、1行の出力を印刷します。

おすすめ記事