web-dev-qa-db-ja.com

2つのファイル間の共通の行

ターミナルで実行する次のコードがあります。

LC_ALL=C && grep -F -f  genename2.txt hg38.hgnc.bed > hg38.hgnc.goi.bed

これは、2つのファイル間の共通の行を提供しません。そこで何が欠けていますか?

10
Marwah Soliman

comm -12 file1 file2を使用して、両方のファイルで共通の行を取得します。

期待どおりに機能するように、ファイルをcommにソートする必要がある場合もあります。

comm -12 <(sort file1) <(sort file2)

man comm から:

-1     suppress column 1 (lines unique to FILE1)
-2     suppress column 2 (lines unique to FILE2)

またはgrepコマンドを使用して、-xオプションを追加し、行全体を一致パターンとして一致させる必要があります。 Fオプションは、grepにパターンに一致することを正規表現一致ではなく文字列として通知します。

grep -Fxf file1 file2

またはawkを使用します

awk 'NR==FNR{seen[$0]=1; next} seen[$0]' file1 file2

これはfile1の行全体を、キーを行全体としてseenという配列に読み取ります(awkでは、$0は現在の行全体を表します)。

NRawkは現在の処理行番号を参照し、FNRは次のようになるため、NR==FNRを条件として使用して、後続のブロックを最初の入力に対してのみ実行しますfle1file2ではありません。 all入力で現在の行番号を参照します。したがって、NRは各入力ファイルに対して一意ですが、FNRはすべての入力に対して一意です。

nextは、awkNRと等しくない、つまりFNRによって読み取られるfile1のすべての行が等しくなるまでawkが残りのコードを続行せずに再開することを伝えています。

次に、次のseen[$0]は2番目にのみ実行されますfile2file2の各行で配列を調べ、その行が配列内に存在する場所に出力します。

別の簡単なオプションは、sortuniqを使用しています:

sort file1 file2|uniq -d

これにより、両方のファイルがソートされて印刷され、uniq -dは重複する行のみを印刷します。しかし、これは両方のファイル自体に重複する行がない場合に許可されます。それ以外の場合は、両方のファイル内に重複する行がある場合でも常に許可されます。

uniq -d <(sort <(sort -u file1) <(sort -u file2))
32
αғsнιη

Linuxで実行しているので、それはGNU/Linuxであり、GNU diffコマンドを使用していると思います。

GNU diffコマンドを実行している場合、これは変更されたすべての行と一般的な行を表示する方法です。

diff \
--old-line-format='-%l
' \
--new-line-format='+%l
' \
--unchanged-line-format=' %l
' \
"$@"

これは従来のdiff出力に似ていますが、ファイル名や区切り線は出力に表示されず、古い行には-が付いており、新しい行には+が前に付いています。先頭にスペースが付きます。

シェルスクリプトの例とテストファイルの結果の出力を次に示します。

$ cat diffcomm.sh
#!/bin/sh
diff \
--old-line-format='-%l
' \
--new-line-format='+%l
' \
--unchanged-line-format=' %l
' \
"$@"
$ cat > filea
a
b
c
d
$ cat > fileb
a
z
d
$ ./diffcomm.sh  filea fileb
 a
-b
-c
+z
 d
$

ラインのクラスごとに出力フォーマットを変更できます。

詳細については、man diffまたはinfo diffまたは GNU diffutilsのドキュメント を参照してください。

3
RobertL