3

タブで区切られたフィールドを持つ 2 つのファイル間でフィールド ($3) の一部を比較する次の作業に苦労しています。ファイルは、他のフィールド $1-2 行ごとに一致しますが、$3 は微妙に異なります。AFの数値である $3 の一部にのみ関心があります。$3 のすべてのサブフィールド (?) はセミコロンで区切られていますが、ご覧のとおり、AF値は常にその位置にあるわけではありません (#2 の場合もあれば、#3 の場合もあります)。3 番目のフィールドのAFの値がファイル間で異なる行を取り出したいと思います。

たとえば、file1 の例を次に示します。

dmel_mitochondrion_genome       18984   AB=0.743;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19066   AB=0.684;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19074   AB=0.321;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19212   AC=8;AF=1.00;AN=8;DP=382;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19285   AC=8;AF=1.00;AN=8;DP=342;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19384   AC=8;AF=1.00;AN=8;DP=400;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19395   AC=8;AF=1.00;AN=8;DP=398;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19461   AB=0.524;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19472   AB=0.527;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19475   AC=8;AF=1.00;AN=8;BaseQRankSum=0.936;DP=$

および例 file2:

dmel_mitochondrion_genome       18984   AB=0.730;AC=4;**AF=1.00**;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19066   AB=0.742;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19074   AB=0.345;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19212   AC=8;AF=1.00;AN=8;BaseQRankSum=1.722;DP=$
dmel_mitochondrion_genome       19285   AC=8;AF=0.50;AN=8;BaseQRankSum=1.721;DP=$
dmel_mitochondrion_genome       19384   AC=8;AF=1.00;AN=8;BaseQRankSum=1.458;DP=$
dmel_mitochondrion_genome       19395   AC=8;AF=1.00;AN=8;DP=391;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19461   AB=0.510;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19472   AB=0.526;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19475   AC=8;AF=0.50;AN=8;BaseQRankSum=-1.732;DP$

取得したい出力は、file1 からの次の行です。

dmel_mitochondrion_genome       18984   AB=0.743;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19285   AC=8;AF=1.00;AN=8;DP=342;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19475   AC=8;AF=1.00;AN=8;BaseQRankSum=0.936;DP=$

またはこのようなもの:

dmel_mitochondrion_genome       18984   AF=0.50  
dmel_mitochondrion_genome       19285   AF=1.00  
dmel_mitochondrion_genome       19475   AF=1.00

awk を使用しようとしましたが、フィールド全体ではなくフィールドの一部を比較する方法がわかりませんでした。最終的に、あるファイルの各行で正規表現を使用して AF の値を見つける方法を見つけましたが、値をキャプチャして別のファイルの別の値と比較する方法がわかりません。どんな助けでも大歓迎です!

4

6 に答える 6

4

次のコマンドは、各ファイルを目的の形式で提供する必要があります。次に、それらに対してdiifを実行できます...

awk '{s=$0; split(s, a, "AF="); split(a[1], a1); split(a[2], a2, ";"); print a1[1] " " a1[2] " AF=" a2[1]}'
于 2012-04-09T22:01:18.353 に答える
2

少し異なるアプローチ

awk '{subList=$3; 
 sub(/.*AF=/, "AF=", subList); sub(/;.*$/, "", subList)
 print $1 "\t" $2 "\t" subList}'  awkTest_20120409_1.txt > awkTest_20120409_1_cln.txt

awk '{subList=$3; 
 sub(/.*AF=/, "AF=", subList); sub(/;.*$/, "", subList)
 print $1 "\t" $2 "\t" subList}'  awkTest_20120409_2.txt > awkTest_20120409_2_cln.txt

diff awkTest_20120409_1_cln.txt awkTest_20120409_2_cln.txt | grep '^<' | sed 's/< //'

**出力**

dmel_mitochondrion_genome       18984   AF=0.50
dmel_mitochondrion_genome       19285   AF=1.00
dmel_mitochondrion_genome       19475   AF=1.00

もちろん、fileNamesを入力と出力、およびのターゲットとして置き換える必要がありますdiff

これがお役に立てば幸いです。

于 2012-04-09T22:20:59.470 に答える
2

AWK 配列をハッシュ テーブルとして使用して、最初に発生したAF値を格納し、次に発生した値と比較できます。

BEGIN { store[0] = 0 }
{
    key = $1 "-" $2
    match($3, /AF=[^;*]+/)
    val = substr($3, RSTART+3, RLENGTH-3)
    if ((key in store) && (store[key] != val))
        print $1,$2,"AF=" store[key]
    else
        store[key] = val
}

ただし、フィルター後差分ソリューションはより洗練されているように見えます。これは、大量のメモリを消費する可能性があるためです。

于 2012-04-09T22:08:24.977 に答える
1

TXR: 扱いにくいテキスト ファイルを扱う分子生物学者向けに作成されました。そして他の人も。

ファイルが巨大になる可能性があるため、行のペアから次のペアまで、メモリ内に何も保持しないようにします ( :vars ()collect 句の によって保証されます)。

ここでは、行がインターリーブされた単一のストリームのように 2 つのファイルを表示するために、ちょっとしたトリックが使用されています。その後、そのストリームを 1 つのファイルであるかのようにパターン マッチできます。

変数 (列 3 の内容) は Lisp 連想リストに解析されるためassoc、関心のあるフィールドの値を検索するために使用できます。文字列単位で比較されます。必要に応じて、0.5 と 0.50 が同じと見なされるように数値に変換できます。

@(next :args)
@(cases)
@file1
@file2
@(or)
@  (throw error "two file names needed")
@(end)
@;
@; functional programming trick: make a bottomless lazy list which returns
@; strings, which are the lines from files f1 and f2, alternating.
@;
@(do (defun make-interleaved-lazy-stream (f1 f2)
       (let ((streams '#(,(open-file f1 "r") ,(open-file f2 "r"))))
         (let ((toggle 0) line)
           (gen (prog1
                  (set line (get-line [streams toggle]))
                  (set toggle (- 1 toggle)))
                line)))))
@(define parse-line (gen id alist))
@gen @id @(coll)@{var /[A-Z]+/}=@val;@(end)
@  (bind alist @[mapcar cons var val])
@(end)
@(next :list @(make-interleaved-lazy-stream file1 file2))
@(collect :vars ())
@  (cases)
@    (parse-line gen id alist1)
@    (parse-line gen id alist2)
@  (or)
@    (throw error `assumption violated: mismatching lines between @file1 and @file2`)
@  (end)
@  (do (let ((AF1 (cdr (assoc "AF" alist1)))
             (AF2 (cdr (assoc "AF" alist2))))
         (if (not (equal AF1 AF2))
           (put-string `@{gen 30} @{id -6}   AF1=@AF1\n`))))
@(end)

走る:

$ txr gendiff.txr file1 file2
dmel_mitochondrion_genome       18984   AF1=0.50
dmel_mitochondrion_genome       19285   AF1=1.00
dmel_mitochondrion_genome       19475   AF1=1.00
于 2012-04-09T22:25:10.727 に答える
0

これは役立つかもしれません -

awk -F'[; =]' '
NR==FNR{ for (i=1;i<=NF;i++) if ($i=="AF") b[++x]=$(i+1); c[x]=$0; next } 
{for (j=1;j<=NF;j++) if ($j=="AF") d[++y]=$(j+1)} 
END {for (z=1;z<=length(b);z++) if (b[z]!=d[z]) print c[z]}' f1 f2

ファイル 1:

[jaypal:~/Temp] cat f1
dmel_mitochondrion_genome       18984   AB=0.743;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19066   AB=0.684;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19074   AB=0.321;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19212   AC=8;AF=1.00;AN=8;DP=382;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19285   AC=8;AF=1.00;AN=8;DP=342;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19384   AC=8;AF=1.00;AN=8;DP=400;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19395   AC=8;AF=1.00;AN=8;DP=398;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19461   AB=0.524;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19472   AB=0.527;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19475   AC=8;AF=1.00;AN=8;BaseQRankSum=0.936;DP=$

ファイル 2:

[jaypal:~/Temp] cat f2
dmel_mitochondrion_genome       18984   AB=0.730;AC=4;AF=1.00;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19066   AB=0.742;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19074   AB=0.345;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19212   AC=8;AF=1.00;AN=8;BaseQRankSum=1.722;DP=$
dmel_mitochondrion_genome       19285   AC=8;AF=0.50;AN=8;BaseQRankSum=1.721;DP=$
dmel_mitochondrion_genome       19384   AC=8;AF=1.00;AN=8;BaseQRankSum=1.458;DP=$
dmel_mitochondrion_genome       19395   AC=8;AF=1.00;AN=8;DP=391;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19461   AB=0.510;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19472   AB=0.526;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19475   AC=8;AF=0.50;AN=8;BaseQRankSum=-1.732;DP$

テスト:

[jaypal:~/Temp] awk -F'[; =]' '
NR==FNR{ for (i=1;i<=NF;i++) if ($i=="AF") b[++x]=$(i+1); c[x]=$0; next } 
{for (j=1;j<=NF;j++) if ($j=="AF") d[++y]=$(j+1)} 
END {for (z=1;z<=length(b);z++) if (b[z]!=d[z]) print c[z]}' f1 f2
dmel_mitochondrion_genome       18984   AB=0.743;AC=4;AF=0.50;AN=8;BaseQRankSum=$
dmel_mitochondrion_genome       19285   AC=8;AF=1.00;AN=8;DP=342;DS;Dels=0.00;FS$
dmel_mitochondrion_genome       19475   AC=8;AF=1.00;AN=8;BaseQRankSum=0.936;DP=$
于 2012-04-09T23:14:46.543 に答える
0

これはあなたのために働くかもしれません:

awk -vfile2=file2 -vOFS='\t' '{sub(/.*AF=[^0-9.-]*/,"",$3);sub(/[^0-9.-]+.*/,"",$3);getline line <file2;sub(/.*AF=[^0-9.-]*/,"",line);sub(/[^0-9.-]+.*/,"",line)};$3!=line{$3="AF="$3;print}' file1

以来file1、値file2を除いて一致します。AF

  • 一行読むfile1
  • 価値$3に還元AF
  • の行をfile2変数に読み込むline
  • 価値lineに還元AF
  • 一致しない場合は( を先頭に追加した後)と比較$3lineて出力$0します。file1$3AF=
于 2012-04-10T00:33:55.897 に答える