使用 awk 计算比率

使用 awk 计算比率
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

awk:命令。行:1:(FILENAME = A FNR = 18)致命:尝试除以零

有人可以帮助解决这个错误吗?

NR==1这里的和 是什么NR>1意思?它在 awk 示例中;我不明白。我知道 NR 是记录数,但为什么我们在这里使用它?

答案1

看起来该示例的作者想象文件 A 和 B 的格式如下:

文件A:

X Y Z
1 2 3
4 5 6

文件B:

6 7 8
o o 0

AWK 示例的作用是创建第四列。这里的NR代表AWK当​​前正在处理的行。在第一行,它将第四个参数设置为字符串“ratio”(列名称),在接下来的所有行中,它将第四个参数设置为第三个参数除以第二个参数。结果:

awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A
X   Y   Z   ratio
1   2   3   1.5
4   5   6   1.2
6   7   8   1.14286
1   2   3   1.5

至于您收到的错误:

awk:命令。行:1:(FILENAME = A FNR = 18)致命:尝试除以零

确保文件 A 的第 18 行包含第 2 列和第 3 列中的数字。

您可以使用 sed 将 'o' 字符转换为 0:

cat A B | sed 's/\bo\b/0/g'

您可以检查第 2 列是否为 0 并进行相应操作:

awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)}

放在一起,你会得到:

cat A B | sed 's/\bo\b/0/g' | awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}'
X   Y   Z   ratio
1   2   3   1.5
4   5   6   1.2
6   7   8   1.14286
0   0   0   N/A

答案2

在给出的例子中,

awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

NR是迄今为止读取的记录数。人们可以在这样的示例中使用它来跳过表的标题,如下所示:

Date        Cost     Quantity
2016/04/10  12.57    3
2016/04/19  11.74    2

因为你不能将“成本”除以“数量”(它们不是数字)。

顺便说一句,你的数据可以有四列(或更多)。但是,awk 允许您分配给不在输入数据中的列。因此,最初$4="ratio"可能是更改现有列,但更可能的是向数据添加一列以反映对连续记录的计算。

错误(除以零)与 的解释是不同的问题NR。您可以检查是否有数字数据$2$3使用模式,例如添加此检查:

产生类似的东西

#!/bin/sh
awk 'function isnum(v) { 
     if ( v ~ /^[0-9.]+$/ ) 
         return 1; 
     else 
         return 0; 
     } 
     (NR==1){$4="ratio"} 
     (NR>1 && NF >= 3 && isnum($2) && isnum($3) && $3 > 0){$4 = ($3)/($2)} 
     {print $1 "\t" $2 "\t" $3 "\t" $4}' A  B

isnum函数已简化,但允许使用无符号小数。

如果您更喜欢单行脚本,请记住 awk 脚本是自由格式的。所以...你可以这样做:

awk 'function isnum(v){if(v~/^[0-9.]+$/)return 1;else return 0;}(NR==1){$4="ratio"}(NR>1&&NF>=3&&isnum($2)&&isnum($3)&&$3>0){$4=($3)/($2)}{print $1"\t"$2"\t"$3"\t"$4}' A  B

相关内容