我有一个描述等位基因频率的文件,我试图使用 awk 打印行,如果最后两列中的频率之一等于或大于 0.01。以下是频率文件的格式:我对最后两个频率感兴趣。
2L 10000133 A 125/125 115/131 0/125 16/131
2L 10000374 A 121/124 143/143 3/124 0/143
根据我对 awk 的有限知识,我编写了以下代码。
cat myfile.txt |
awk ' BEGIN { {FS="/"}{OFS="\t"}
if( ($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01"))
{ print $1,$2 }
}' > myfilteredfile.txt
但是,输出文件 myfilteredfile.txt 为空。我预计输出文件会打印:
2L 10000133
2L 10000374
...因为这两行最后两列中的频率都等于或大于 0.01。有什么建议吗?
答案1
您现有的脚本有两个问题。
第一个是分隔符:您想要按空格和斜杠进行分割;因此您需要指定一个与之匹配的正则表达式,并将其用作FS
: FS="[ /]+"
。
第二个是所有代码都在BEGIN
块中。您需要初始化BEGIN
块中的分隔符(或其他地方,例如使用特定的 AWK 参数),然后使用匹配器块来处理这些行。
这个版本的工作原理:
awk 'BEGIN { FS="[ /]+"; OFS="\t" }
(($8>0) && ($8/$9 >= "0.01") || ($10>0) && ($10/$11 >= "0.01")) {
print $1, $2
}' myfile.txt
严格来说,最好使用0.01
而不是"0.01"
因为您要匹配数值:
awk 'BEGIN { FS="[ /]+"; OFS="\t" }
(($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01)) {
print $1, $2
}' myfile.txt
答案2
$ awk '{ split($(NF-1),a,/\//) } { split($NF,b,/\//) } a[1]/a[2] > 0.01 || b[1]/b[2] > 0.01 { print $1, $2 }' file.in
2L 10000133
2L 10000374
这将在字符上分别拆分最后两个字段/
,并将各部分存储在两个数组a
和中b
。如果执行任一除法时得出的数字大于 0.01,则输出前两个字段。
$NF
是输入记录(行)中最后一个字段(列)的值。是$(NF-1)
倒数第二个字段的值。
您的代码的问题是您正在做所有事情BEGIN
块中执行了所有操作。该块主要用于初始化,并将执行前实际上已经读取了任何数据。FS
其他答案指出的选择值也存在问题。
当数字用作数字时,您也不需要引用数字。
答案3
Inawk
的BEGIN{...}
部分在从输入读取输入行之前运行,因此在您的代码中实际上awk
没有读取任何输入,这就是它不返回任何内容的原因。如果你想喂它,你需要使用getline
,但它只会读取一行,你可以使用for
循环来读取全部。
另一个问题是,当您使用FS="/"
它将行拆分为由 分隔的字段时/
,但问题是不存在,$8
因为最大字段只有 5 个,而提交的字段如下125 115
、、、等。131 0
125 16
您可以使用此代码来实现您想要的目的。另请注意,awk
可以直接从文件读取,不需要使用cat
那里
awk -F'[/ ]+' 'BEGIN{ OFS="\t"}
{if( ($8>0) && ($8/$9 >= 0.01) || ($10>0) && ($10/$11 >= 0.01))
{ print $1,$2 }
}' infile