![为什么 GNU awk 实现限制在实践中似乎不起作用?](https://linux22.com/image/174710/%E4%B8%BA%E4%BB%80%E4%B9%88%20GNU%20awk%20%E5%AE%9E%E7%8E%B0%E9%99%90%E5%88%B6%E5%9C%A8%E5%AE%9E%E8%B7%B5%E4%B8%AD%E4%BC%BC%E4%B9%8E%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8%EF%BC%9F.png)
这一页提到 GNU awk 实现限制时提到字段大小和文字字符串大小的限制是MAX_INT
。
但是,当我将长字符串文字声明为变量并尝试使用函数查找其长度时length
,当字符串长度超过 308 个字符时,该函数似乎会中断。下面的例子:
BEGIN {
avar=1234... #309 characters
print length(avar) #prints 3 but prints right length when length < 309
}
但是,以下命令行适用于 1000 个字符:
echo 1234... | awk '{print length($1)}' #tested and works for 1000 characters
我使用的是 CentOS 7 系统,我的 awk 版本是 4.0.2。
关于为什么会出现这种差异有什么建议吗?
答案1
您尝试做的事情可能会更容易重复:
awk 'BEGIN {
avar='"$(printf '%0200d' 0)"' #309 characters
print avar,length(avar) #prints 3 but prints right length when length < 309
} '
其中打印0 1
,这意味着 200 个零的整个列表被 awk 转换为一个单个0
,这似乎暗示这就是价值写有 200 个零的整数。
让我们给它一些其他值(8 后跟 200 个零):
➤ awk 'BEGIN {
avar='"$(printf '8%0200d' 0)"' #309 characters
print avar,length(avar) #prints 3 but prints right length when length < 309
} '
799999999999999975786497770008289327579602620364018901185934007602774787484432604273570707237650014944220099327791059265457085874946227877115080328377919022968188728534319854489454506449337030839107584 201
这是 的浮点近似值8e200
。这很容易通过以下方式确认:
➤ awk 'BEGIN {
avar='"$(printf '8%0200d' 0)"' #309 characters
print avar,length(avar) #prints 3 but prints right length when length < 309
printf "%15e\n",avar
} '
799999999999999975786497770008289327579602620364018901185934007602774787484432604273570707237650014944220099327791059265457085874946227877115080328377919022968188728534319854489454506449337030839107584 201
8.000000e+200
因此,代码赋值 ( ) 中给出的数字avar=
被(正确地)处理为数值。双浮点数最多只能存储 308 的指数(不包括次正规数)。因此,超过 308 位的数值不能转换为浮点数。
➤ ➤ awk 'BEGIN {
avar='"$(printf '8%0308d' 0)"' #309 characters
print avar,length(avar) #prints 3 but prints right length when length < 309
printf "%15e\n",avar
} '
inf 3
inf
不过,作为字符串,用双引号 ( avar="..."
) 括起来是没有问题的。
➤ awk 'BEGIN {
avar="'"$(printf '8%0600d' 0)"'" #309 characters
print avar,length(avar) #prints 3 but prints right length when length < 309
} '
8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 601
在数据来自管道(或文件)的情况下,数据被假定为字符串(除非强制转换为具有data + 0
或类似的数字),并且其长度是其字符数。
$ printf '8%02000d0\n' 0 | awk '{print length($1)}'
2002