我正在努力完成以下任务:使用制表符分隔的字段比较两个文件之间的字段部分($ 3)。这些文件匹配其他字段$ 1-2 line for line但$ 3略有不同。我只对3美元的一部分感兴趣, AF 的数值。 $ 3中的所有子字段(?)都用分号分隔,但正如您所看到的, AF 值并不总是在位置(有时它是#2,有时是#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=$
和示例文件2:
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的值,但不知道如何捕获该值以将其与另一个文件中的另一个值进行比较。非常感谢任何帮助!
答案 0 :(得分: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]}'
答案 1 :(得分: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
}
然而,filter-then-diff解决方案似乎更优雅,因为这个解决方案有可能消耗大量内存。
答案 2 :(得分: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
的目标。
我希望这会有所帮助。
答案 3 :(得分:1)
TXR:为使用crummy文本文件的分子生物学家创建。还有其他人。
因为文件可能很大,我们避免在内存中保留从一对线到下一行的任何内容(由collect子句中的:vars ()
确保)。
这里使用了一些技巧来使两个文件看起来像一个单独的流,具有交错的行。然后,我们可以对该流进行模式匹配,就像它是一个文件一样。
变量(第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
答案 4 :(得分: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
[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=$
[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=$
答案 5 :(得分: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
值$3
与line
进行比较并从$0
输出file1
(在$3
前加AF=
之后),如果它们不匹配。