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