同じテキストファイル内の異なる行に表示される複数のビットの情報を抽出する方法


8

同じテキストファイル内の異なる行にあるシーケンスIDとクラスター番号を抽出しようとしています。

入力は次のようになります

>Cluster 72
0   319aa, >O311_01007... *
>Cluster 73
0   318aa, >1494_00753... *
1   318aa, >1621_00002... at 99.69%
2   318aa, >1622_00575... at 99.37%
3   318aa, >1633_00422... at 99.37%
4   318aa, >O136_00307... at 99.69%
>Cluster 74
0   318aa, >O139_01028... *
1   318aa, >O142_00961... at 99.69%
>Cluster 75
0   318aa, >O300_00856... *

必要な出力は、1つの列にシーケンスID、2番目に対応するクラスター番号です。

>O311_01007  72
>1494_00753  73
>1621_00002  73
>1622_00575  73
>1633_00422  73
>O136_00307  73
>O139_01028  74
>O142_00961  74
>O300_00856  75

誰かがこれを手伝ってくれる?


シーケンスIDは常に、で始まらない行の3dスペース区切りフィールドになり>ますか?また、あなたは私たちの姉妹サイト、バイオインフォマティクスに興味があるかもしれません。
terdon 2018年

回答:


13

awkで:

awk -F '[. ]*' 'NF == 2 {id = $2; next} {print $3, id}' input-file
  • スペースまたはピリオドでフィールドを分割します -F '[. ]*'
  • 2つのフィールドの>Cluster行(行)を使用して、2番目のフィールドをIDとして保存し、次の行に移動します
  • 他の行で、3番目のフィールドと保存されたIDを出力します

フィールド数をキーオフするのでは$1 == ">Cluster"なくNF == 2、ファイル内の他の内容に応じて、ではなく明示的に探す方がよい場合があります。
モンティハーダー2018年

5

awkこれに使用できます:

awk '/>Cluster/{
      c=$2;
      next
    }{
      print substr($3,2,length($3)-4), c
    }' file

最初のブロックステートメントは、クラスターIDをキャプチャしています。2番目のブロックステートメント(既定のステートメント)は、必要なデータを抽出して印刷します。


" "引数として与える必要はありませんprint。引数を区切るにはカンマを使用するだけで、引数を区切るためにデフォルトのスペースであるOFSが使用されます。
muru

4

Rubyをワンライナーとして使用する別の方法を次に示します。

ruby -ne 'case $_; when /^>Cluster (\d+)/;id = $1;when /, (>\w{4}_\w{5})\.\.\./;puts "#{$1} #{id}";end' input_file

または複数行にまたがって:

ruby -ne 'case $_
when /^>Cluster (\d+)/
  id = $1
when /, (>\w{4}_\w{5})\.\.\./
  puts "#{$1} #{id}"
end' input_file

awkRubyと正規表現を知っている場合は、バージョンよりも読みやすいだけだと思います。おまけとして、このコードは周囲のテキストを探すため、単に行を分割するよりも少し堅牢かもしれません。


1

Perl:

$ perl -ne 'if(/^>.*?(\d+)/){$n=$1;}else{ s/.*(>[^.]+).*/$1 $n/; print}' file 
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75

説明

  • perl -ne:入力ファイルを1行ずつ読み取り(-n)、-e各行に指定されたスクリプトを適用します。
  • if(/^>.*?(\d+)/){$n=$1;}:この行がで始まる場合>は、行の最後にある最も長い数字を見つけて、として保存します$n
  • else{ s/.*(>[^.]+).*/$1 $n/; print:行がで始まらない場合は>、すべてを()の.後に続く非文字の最も長いストレッチ、つまりシーケンス名(正規表現の一致をキャプチャしたため)との現在の値に置き換えます。>>[^.]+$1$n

または、よりawkのようなアプローチの場合:

$ perl -lane 'if($#F==1){$n=$F[1]}else{$F[2]=~s/\.+$//; print "$F[2] $n"}' file 
>O311_01007 72
>1494_00753 73
>1621_00002 73
>1622_00575 73
>1633_00422 73
>O136_00307 73
>O139_01028 74
>O142_00961 74
>O300_00856 75

これは、さまざまなawkアプローチと同じ基本的な考え方を実行するためのやや面倒な方法です。完成のためとPerlファンのために含めています。説明が必要な場合は、awkソリューションを使用してください:)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.