在 awk 脚本中使用除法

在 awk 脚本中使用除法

我有一个描述等位基因频率的文件,我试图使用 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

InawkBEGIN{...}部分在从输入读取输入行之前运行,因此在您的代码中实际上awk没有读取任何输入,这就是它不返回任何内容的原因。如果你想喂它,你需要使用getline,但它只会读取一行,你可以使用for循环来读取全部。

另一个问题是,当您使用FS="/"它将行拆分为由 分隔的字段时/,但问题是不存在,$8因为最大字段只有 5 个,而提交的字段如下125 115、、、等。131 0125 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

相关内容