如何跳过第一行以某种格式打印列并在下面进行一些算术运算后?接下来可以吗?
输入
#filename
4e+06 5e+06 6e+06
5e+06 5e+06 6e+06
代码:
BEGIN { CONVFMT="%0.17f" }
function t(n, s) {
s=index(n,".")
return (s ? substr(n,1,s+2) : n)
}
FR>1 {print t($1-1000),t($2)}
答案1
您刚刚在 awk 脚本的最后一行中犯了一个拼写错误:它应该读取FNR
而不是FR
在地址中:
BEGIN { CONVFMT="%0.17f" }
function t(n, s) {
s=index(n,".")
return (s ? substr(n,1,s+2) : n)
}
FNR>1 {print t($1-1000),t($2)}
这在这里按预期工作。
由于拼写错误,地址与FR>1
任何数据行都不匹配:FR
是一个常量,并且条件FR>1
始终为假。这就是为什么你没有得到任何输出。
答案2
有多种方法可以跳过第一行。
NR>1{ … } # For every record after the first.
BEGIN{ getline } # Only on the start, read the first line
!var{var=1;next} # If var is unset, set it and skip one line.
FNR>1{ … } # For records after the first for every file listed.
该变量NR
表示“记录数”,并且假设使用默认记录分隔符(换行符),这也是每行的数量。第一行(在这种情况下)被编号1
。如果NR
大于1
,则大括号内执行的内容仅在第一行之后执行。
相反,变量FNR
表示命令行 ( ) 中列出的每个文件的记录号重置为零awk 'script' file1 file2 filen …
。这NR>1
与每个新文件完全相同,但会重置。
修剪功能
此外,您有一个函数定义,t(n,s)
其目标(根据您的评论)“将数字削减为小数点后两位”,但它没有正确执行此操作。
在该函数定义中,有一个查找点的命令。假设点是小数点分隔符:
s=index(n,".")
然后(作为字符串)在点后两个字符处剪切字段的字符串。对于没有指数的数字,可以正确修剪小数,但该数字正在使用指数,例如1.2345678e3
。它将被修剪为1.23
.当然,这与正确修剪到两位小数不同1234.56
。
要正确修剪数字,您必须考虑指数。该int
函数正是这样做的:
function ti(n){ return( int(100*n)/100 ) }
但您可以更好地依赖应用于浮点数的近似值:
function tf(n){ return( sprintf( "%.2f",n ) ) }
它们的近似程度(实际上是类型)不同。使用 int 的函数向零舍入到较小的整数(对于正数)。对于像 之类的数字3.7
,无论如何都会向下舍入3
,误差为0.7
。具有浮点数的函数四舍五入到最接近的整数。最大误差为0.5
.上面的数字,如3.7
,四舍五入为4
,误差仅为0.3
。所以,一个是一个向零舍入的近似值,另一个是四舍五入到最接近的整数。一个的最大误差为0.9
,另一个的最大误差仅为0.5
。浮点近似唯一奇怪的事情是它有时0.5
向上舍入,有时0.5
向下舍入。这是为了平衡向上舍入和向下舍入。
很明显,0.1、0.2、0.3 和 0.4 应向下舍入为 0。
这会产生 0.1、0.2、0.3 和 0.4 的误差。
而是0.9、0.8。 0.7 和 0.6 向上舍入为 1。
这会产生 -0.1、-0,2、-0.3、-0.4 的误差
所有这些错误(随机输入的平均错误)都会平衡。
但如果我们总是向上舍入 0.5,则会产生 0.5 的恒定误差。
为了平衡它,一旦我们向下舍入,下一次我们向上舍入。
或者,正如通常写的那样:圆关系 (0.5) 为偶数。
printf '%s ' $l; echo; printf '%-3.0f ' $l; echo
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2
请注意,0.5
四舍五入0
(向下)和1.5
四舍五入2
(向上)
精确
您应该使用CONVFMT="%.16g"
作为转换浮点数的格式。
格式f
会删除有效数字,如下所示:
$ awk 'BEGIN{var=1.23456789e-8;printf "%.9f\n",var}'
0.000000012
只有两位有效数字。而是一种g
格式:
$ awk 'BEGIN{var=1.23456789e-8;printf "%.9f\n",var}'
1.23456789e-08
将保留 9 位有效数字(数字)。
文件名
它对于应用于多个文件的 awk 命令很有用,例如:
$ awk 'FNR>1{print $1}' file1 file2 file3
要使用 FNR 而不是 NR,因此条件依次适用于每个文件。