web-dev-qa-db-ja.com

2つのテキストファイルを比較し、一致する行を見つける

2つのファイルAとBがあります。Aは次のようになります(4〜6行):

GAGA
CAGA
GGGT
TATT

ファイルBは数千行の非常に大きなファイルです。短い例を次に示します。

AAATGTCAAGAGACAGAAATGTCAAGAGGGT
AAGGGGGTTTATAATCATAAATCAAAGAAAT
ATATACAGAAATGTCAAGAGACAGAAATGTC
TCAAGAGACAGAAATGTCAAGAGGGTCTATA
AAGAGGGTCTATAATCATAAATCAAAGAAAT
AAGAGGGTCTATAATCATAAATCAAAGAAAT
ATACAGAAATGTCAAAACAGAAATGTCAAGG
ATATACAGAATATACAGAAATGTCAAGTTAT
ACAGAATATACAGAAATGTCAAGTTATATAC
ATATACAGAAATGTCAAGAGACAGAAATGTC
TCAGAATATAGTATTCTATTATATACAGAAA
AATATAGTATTCTATTATATACAGAAATGTC
GAATATACAGAAATGTCAAGTTATATACAGA
TATACAGAATATAGTATTCTATTATATACAG
CAGAATATAGTATTCTATTATATACAGAATA
AGTTATATACAGAATATAGTATTCTATTATA
TACAGAATATAGTATTCTATTATATACAGAA
CAGAAATGTCAAGTTATATACAGAATATAGT

ファイルBのすべての行でファイルAのすべての文字列を検索し、Aの各文字列を含むファイルBの最初の10行を回復する必要があります。grepとawkを試しましたが、良い結果は得られませんでした。ありがとう

4
Alejandro

パターンは4〜6行しかないので、ORパターンで使用しませんか?2番目のファイル "bigDNA.txt"で動作する10個の一致に制限する例:

grep -E 'GAGA|CAGA|GGGT|TATT' -m 10 bigDNA.txt

これにより、ファイルpatt.txtからパターンを手動で入力する手間が省けます。 |で行を結合します(各行に|を追加し、改行を削除し、末尾の|を削除します):

grep -E "$(sed 's#$#|#' patt.txt | tr -d '\n' | sed 's#|$##')" -m 10 bigDNA.txt
5
Lekensteyn

whileループで「ファイルA」を反復処理してみましたか?

while read string
 do grep "$string" file-B | head -10
done < file-A

または1行で:

while read string; do grep "$string" file-B | head -10; done < file-A
2
h3rrmiller

これはうまくいけば読めるスクリプトです。

FIRSTFILEには、1行に1つのアイテムが含まれます(余分なスペースはありません)。BIGFILEには、一致させたい大きなリストが含まれています。

awk -F, '
  BEGIN{
     regexp="__NOTMATCHING__"
     linematched=0
     while(( getline line<"FIRSTFILE") > 0 ) {
        nb_items[line]=0; #initialise a counter in items["...."]
        regexp=regexp"|"line  #we create a "egrep-like" regexp matching each item
     }

  }

#main : read each line. 
#           - save each matching lines. 
#           - and increment each corresponding counters. 
  {  if ( $0 ~ regexp ) {
        matchinglines[++linematched]=$0
        for ( item in nb_items ) {
           #for each matching item, we also increment that item s number
           if ( $0 ~ item ) { 
              nb_items[item]++ ; 
           }
        }
     }
  }

END  {  #at the end, we print all items which have nb_item[item]>=10
        for ( item in nb_items ) {
           if (nb_items[item] >= 10) {
              print "for this item:",item
              for (i;i<=linematched;i++) {
                 if ( matchinglines[i] ~ item ) {
                    print matchinglines[i] ; 
                 }
              }
           }
        }
     }
   ' BIGFILE
1
Olivier Dulac

これは、任意の文字列に一致する最初の10行を印刷します。

grep -m 10 -Ff motifs sequence.fa 

これは、各モチーフを読み取り、それを計算して最初の10行を印刷するため、各モチーフに対して10行を印刷します。

while read mot; do grep -m 10 "$mot" sequence.fa; done < motifs

ただし、これはDNAシーケンスのように見えます。つまり、改行は完全に任意であり、次のように一致させることができます。

ACTG[〜#〜] ga [〜#〜]
[〜#〜] ga [〜#〜]

これらのアプローチでは、上記のGAGAは一致としてカウントされず、これはおそらくあなたが望むものではありません。代わりに、検索する前にすべてを1行に入れることをお勧めします。あなたは一致する線を求めているので、これらのモチーフのそれぞれをそのコンテキストで欲しいと思います。したがって、これを適切に行うには、改行で分割されたモチーフを一致させ、まずファイルを [〜#〜] tbl [〜#〜] 形式に変換します。私は何年も同僚(Pepに感謝)が書いた同じawkスクリプトを使用しています。

#!/bin/sh
gawk '{
        if (substr($1,1,1)==">")
        if (NR>1)
                    printf "\n%s\t", substr($0,2,length($0)-1)
        else 
            printf "%s\t", substr($0,2,length($0)-1)
        else 
                printf "%s", $0
}END{printf "\n"}'  "$@"

上記のスクリプトを$PATHのどこかにFastaToTblとして保存し(例:/usr/local/bin)、実行可能にします(chmod a+x /usr/local/bin/FastaToTbl)。次に、FASTA形式のシーケンスをパイプ処理するだけで、.tbl形式を出力します。ここで、識別子とシーケンスはすべて同じ行にあります。

したがって、FastaToTblを設定したら、次のコマンドを実行できます。

while read mot; 
do 
    FastaToTbl sequence.fa | grep -Po ".{10}$mot.{10}" | head -n 10 
done < motifs   

上記は、各パターンの最初の10個の一致を提供し、改行で分割されたモチーフにも一致します。また、一致したパターンの両側に10文字を印刷します。{10}を別の数字に変更して、この動作を制御します。

1
terdon