4

我正在打印一个包含 100 列的数组,我希望所有列都有 2 位小数。我想使用 print $0 而不必单独指定所有列的格式。

OFMT 确实可以使用 0 美元:

echo '0.77767686 0.76555555 0.6667667 0.77878878' |awk '{CONVFMT="%.2g";OFMT="%.2g";print ($0+0);print ($0+0)"";print $0}' 

结果:

0.78
0.78
0.77767686 0.76555555 0.6667667 0.77878878
4

3 回答 3

10

请注意,所有输入都被视为字符串,直到通过使用方式进行隐式转换。

OFMT用于将字符串转换为数字时打印数字,例如:

<<< 0.77767686 awk '{ print 0+$0 }' OFMT='%.2g'

CONVFMT当数字显式转换为字符串时使用,例如:

<<< 0.77767686 awk '{ print "" 0+$0 }' CONVFMT='%.2g'

两种情况下的输出:

0.78

后者转换$0为数字,然后将其与空字符串连接。

为了为每一列实现这一点,我建议使用输入和输出记录分隔符的合理设置:

<<< '0.77767686 0.76555555 0.6667667 0.77878878' \
awk '{ print 0+$0 RT }' CONVFMT='%.2g' RS='[ \t\n]+' ORS=''

请注意这两种转换,首先是一个数字,0+$0然后通过将其与 连接起来返回一个字符串RTRT将设置为匹配的记录分隔符。请注意,这是 GNU awk 特定的,对于更便携的解决方案,请使用循环,例如:

<<< '0.77767686 0.76555555 0.6667667 0.77878878' \
awk '{ for (i=1; i<=NF; i++) $i+=0 } 1' CONVFMT='%.2g'

两种情况下的输出:

0.78 0.77 0.67 0.78

编辑 - 回复@BeeOnRope

@BeeOnRope 是正确的,OFMT在 print 函数调用时用作格式说明符sprintf(),而CONVFMT在其他转换中使用。这是一个说明差异的示例:

<<< 0.77767686 awk '{ n=0+$1; s=""n; print n, s }' OFMT='%.2g' CONVFMT='%.3g'

输出:

0.78 0.778

GNU awk 手册中的两个相关部分:

于 2012-10-15T05:03:33.020 回答
4

为什么不使用for循环?

echo '0.77767686 0.76555555 0.6667667 0.77878878' |awk '{ for (i=1; i<=NF; i++) printf "%.2f\n", $i }'

结果:

0.78
0.77
0.67
0.78
于 2012-10-13T12:34:05.080 回答
1

正如其他人所提到的,您需要将该字段视为一个数字才能进行转换。要结合其他一些想法,您可以尝试:

awk '{ for (i=1; i<=NF; i++) $i += 0; print }'

这会将每个字段转换为一个数字。您可以使用$7 += 0等转换单个字段。您可以通过使用if (match($i, ...))一些正则表达式来仅选择您想要转换的数字来获得更好的结果。

于 2012-10-15T06:31:02.510 回答