use*_*271 5 input numeric-data gawk
根据$ man gawk
,该strtonum()
函数可以将字符串转换为数字:
strtonum(str)
检查 str,并返回其数值。如果 str 以前导 0 开头,则将其视为八进制数。如果 str 以前导 0x 或 0X 开头,则将其视为十六进制数。哦?否则,假设它是一个十进制数。
如果字符串0
以前导 开头,则将数字视为八进制,而如果以 开头,0x
则将其视为十六进制。
我已经运行这些命令来检查我对函数的理解:
$ awk 'END { print strtonum("0123") }' <<<''
83
$ awk 'END { print strtonum("0x123") }' <<<''
291
Run Code Online (Sandbox Code Playgroud)
该字符串"0123"
被正确地视为包含八进制数并转换为十进制数83
。同样,字符串"0x123"
被正确地视为包含十六进制数并转换为十进制数291
。
现在,如果我运行相同的命令,但将数字字符串从程序文本移动到输入数据,会发生以下情况:
$ awk 'END { print strtonum($1) }' <<<'0123'
123
$ awk 'END { print strtonum($1) }' <<<'0x123'
291
Run Code Online (Sandbox Code Playgroud)
我理解第二个结果,它与前面的命令相同,但我不理解第一个。为什么 gawk 现在将其0123
视为十进制数,即使它以0
表征八进制数的前导开头?
我怀疑它与strnum 属性有关,因为出于某种原因1,gawk 将此属性提供给0123
但不提供给0x123
:
$ awk 'END { print typeof($1) }' <<<'0123'
strnum
$ awk 'END { print typeof($1) }' <<<'0x123'
string
Run Code Online (Sandbox Code Playgroud)
1这可能是由于awk 实现之间的差异:
澄清一下,只有来自少数来源的字符串(此处引用 POSIX 规范): [...] 如果它们的值恰好是数字(允许前导和尾随空格,实现之间存在差异),则将被视为数字字符串 支持十六进制、八进制、inf、nan...)。
我正在使用 gawk version 4.2.62
,输出$ awk -V
是:
GNU Awk 4.2.62, API: 2.0 (GNU MPFR 3.1.4, GNU MP 6.1.0)
Run Code Online (Sandbox Code Playgroud)
这与广义的strnum
GAWK 4.2 版本中的通用处理有关。
看起来像数字的输入值被视为strnum
值,在内部表示为同时具有字符串和数字类型。\xe2\x80\x9c0123\xe2\x80\x9d 看起来像一个数字,因此它被处理为strnum
. strtonum
旨在处理字符串和数字输入;它首先寻找数字,当遇到输入数字时,返回该数字而不进行转换:
NODE *\ndo_strtonum(int nargs)\n{\n NODE *tmp;\n AWKNUM d;\n\n tmp = fixtype(POP_SCALAR());\n if ((tmp->flags & NUMBER) != 0)\n d = (AWKNUM) tmp->numbr;\n else if (get_numbase(tmp->stptr, tmp->stlen, use_lc_numeric) != 10)\n d = nondec2awknum(tmp->stptr, tmp->stlen, NULL);\n else\n d = (AWKNUM) force_number(tmp)->numbr;\n\n DEREF(tmp);\n return make_number((AWKNUM) d);\n}\n
Run Code Online (Sandbox Code Playgroud)\n因此 \xe2\x80\x9c0123\xe2\x80\x9d 变为数字 123,并strtonum
直接返回该值。
\xe2\x80\x9c0x123\xe2\x80\x9d \xe2\x80\x99t 看起来不像一个数字(根据上面给出的链接中定义的规则),因此它被作为字符串处理,并像你\xe2\x80一样处理\x99d 期待strtonum
.
AWK 中数字的定义如下:
\n\n\n输入字符串被分解为两部分:一个初始的、可能为空的空白字符序列(由isspace ()指定)和一个解释为浮点常量的主题序列。
\n主题序列的预期形式是可选的
\n\'+\'
或\'-\'
符号,然后是可选地包含 <period> 的非空数字序列,然后是可选的指数部分。指数部分由\'e\'
或组成\'E\'
,后跟一个可选符号,最后跟一个或多个小数位。以第一个数字或 <period>(以先出现者为准)开始的序列被解释为 C 语言的浮动常量,如果指数部分和 <period> 均未出现,则假定 a 位于最后一位数字之后字符串。如果主题序列以 <hyphen-minus> 开头,则转换产生的值将被否定。
\n