両方のファイルの正規表現

両方のファイルの正規表現

@で始まる4行のブロックで構成される2つのファイルがあります。一致して注文されます。ファイルが大きすぎて(> 10 GB)、各ファイルの最初の3ブロック(12行)をここに入れました。

最初:Rファイル(参照ファイル):

@NB551168:120:HTKN2BGX5:1:11101:3598:1051 2:N:0:NATC
CAATCTCTAAAGTTT
+
AA/A/EEEE///EEE
@NB551168:120:HTKN2BGX5:1:11101:24202:1051 2:N:0:NTCG
TGAGACCGGGTGTTG
+
AAAAAAEEE///<AA
@NB551168:120:HTKN2BGX5:1:11101:4381:1051 2:N:0:NCTT
GCTACTCCTAAGGCA
+
A////6/////EE//

2番目:Iファイル(インデックスファイル):

@NB551168:120:HTKN2BGX5:1:11101:3598:1051 1:N:0:NATC
NATC
+
#EEE
@NB551168:120:HTKN2BGX5:1:11101:24202:1051 1:N:0:NTCG
NTCG
+
#EEE
@NB551168:120:HTKN2BGX5:1:11101:4381:1051 1:N:0:NCTT
NCTT
+
#EEA

出力ファイルには以下を含める必要があります(ブロックあたり(4行)):

  1. 最初の行はR2とまったく同じです(スペースがあるのでそれを維持することが重要です)。
  2. Iファイルの2行目の4文字(常に4文字)をRファイルの2行目の先頭に連結します。
  3. Rファイルの3行を3行に保ちます。
  4. Iファイルの行4(すべての文字)をRファイルの行4の先頭に接続します。
  5. すべてのブロックに対してこれを行います。

出力例:

@NB551168:120:HTKN2BGX5:1:11101:3598:1051 2:N:0:NATC
NATCCAATCTCTAAAGTTT
+
#EEEAA/A/EEEE///EEE
@NB551168:120:HTKN2BGX5:1:11101:24202:1051 2:N:0:NTCG
NTCGTGAGACCGGGTGTTG
+
#EEEAAAAAAEEE///<AA
@NB551168:120:HTKN2BGX5:1:11101:4381:1051 2:N:0:NCTT
NCTTGCTACTCCTAAGGCA
+
#EEAA////6/////EE//

本当にありがとうございます。

答え1

#!/usr/bin/perl

use strict;

my $f1 = shift;
my $f2 = shift;

open(F1,"<",$f1) || die "couldn't open '$f1' for read: $!\n";
open(F2,"<",$f2) || die "couldn't open '$f2' for read: $!\n";

# set the input record separator (IRS) to '@'
$/='@';

# Normally the IRS is found at the END of a record, but your input
# files START with the input record separator, so we need to throw
# away the first (bogus) input record (i.e. everything from the start
# of the files to the first @ characters in them. in other words, the
# first @ characters in both files.)
my $junk = <F1>;
$junk = <F2>;

while (!eof(F1) && !eof(F2)) {
  my @record1 = split(/\n/, <F1>);
  my @record2 = split(/\n/, <F2>);

  printf "%s%s\n", $/, $record1[0];  # prepend the IRS
  printf "%s%s\n", substr($record2[1],0,4), $record1[1];
  printf "%s\n",   $record2[2];
  printf "%s%s\n", $record2[3], $record1[3];
};

close(F1);
close(F2);

これにより、読み取るために両方のファイルを開き、$/Perlの入力レコード区切り変数を1文字@に設定します。

その後、両方のファイルがEOFに達していない場合は、各ファイルから1つのレコードを読み取り、レコードを配列に分割し(改行を区切り\n文字として使用)、指定したようにマージされたレコードを出力します。

Perl配列は1ではなく0から始まります。たとえば、$record1[0]file1に書き込まれた最初の行は次のようになります。

スクリプトをファイル(たとえばhassan.pl)に保存して実行可能にしたら、chmod +x hassan.pl次のように実行します。

出力例:

$ ./hassan.pl file1.txt file2.txt  
@NB551168:120:HTKN2BGX5:1:11101:3598:1051 2:N:0:NATC
NATCCAATCTCTAAAGTTT
+
#EEEAA/A/EEEE///EEE
@NB551168:120:HTKN2BGX5:1:11101:24202:1051 2:N:0:NTCG
NTCGTGAGACCGGGTGTTG
+
#EEEAAAAAAEEE///<AA
@NB551168:120:HTKN2BGX5:1:11101:4381:1051 2:N:0:NCTT
NCTTGCTACTCCTAAGGCA
+
#EEAA////6/////EE//

diff(この出力が必要なものと正確に一致していることを確認しました。)

答え2

つまり、その+行とで始まる行を除いて、この行の前にすべての@行を貼り付けます。IR

理由を理解すると、とても簡単になります。

sed '/^[@+]/s/.*//' I|paste -d '' - R
  • /^[@+]/+またはで始まる行の選択@
  • s/.*//この行を消す
  • paste -d '' - R区切り記号()(パイプ入力の場合)なしで結果を-ファイルに貼り付けます。-d ''R

答え3

Gnu sedにアクセスできる場合は、次のことができます。

$ sed -e 'R I' R | sed -ne 'p;n;n;h;n;G;s/\n//p'

関連情報