修剪功能

修剪功能

如何跳过第一行以某种格式打印列并在下面进行一些算术运算后?接下来可以吗?

输入

#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,因此条件依次适用于每个文件。

相关内容