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

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

同じテキスト ファイル内の異なる行に出現するシーケンス 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

誰かこれについて助けてくれませんか?

答え1

awk の場合:

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

答え2

これには以下を使用できますawk:

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

最初のブロック ステートメントはクラスター ID をキャプチャします。2 番目のブロック ステートメント (デフォルト) は必要なデータを抽出し、それを出力します。

答え3

以下は、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

Ruby と regexen を知っていれば、このバージョンの方が読みやすいだけだと思いますawk。おまけに、このコードは周囲のテキストを探すので、単純に行を分割するよりも少し堅牢かもしれません。

答え4

パール:

$ 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: 入力ファイルを行ごとに読み取り ( )、各行に-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 ソリューションを使用してください :)。

関連情報