您在这里处理两个相似但不同的问题,awk 输入中的非十进制数据和awk 程序中的非十进制文字。
参见the POSIX-1.2004 awk specification,词汇约定:
8. The token NUMBER shall represent a numeric constant. Its form and numeric value [...]
with the following exceptions:
a. An integer constant cannot begin with 0x or include the hexadecimal digits 'a', [...]
所以 awk(可能您使用的是 nawk 或 mawk)表现“正确”。 gawk(从 3.1 版开始)默认支持非十进制(八进制和十六进制)文字数字,但使用 --posix 开关会按预期将其关闭。
在这种情况下,正常的解决方法是使用定义的 数字字符串 行为,其中数字字符串将被有效地解析为 C 标准 atof() 或 strtod() 函数,它支持0x-前缀数字:
$ echo "0x14" | nawk '$1+1<=0x15 {print $1+1}'
<no output>
$ echo "0x14" | nawk '$1+1<=("0x15"+0) {print $1+1}'
21
这里的问题是这不太正确,就像POSIX-1.2004 also states:
A string value shall be considered a numeric string if it comes from one of the following:
1. Field variables
...
and after all the following conversions have been applied, the resulting string would
lexically be recognized as a NUMBER token as described by the lexical conventions in Grammar
更新:gawk 的目标是“2008 POSIX.1003.1”,但请注意,自 2008 年版(参见 IEEE Std 1003.1 2013 edition awk here)以来,允许 strtod() 和实现相关的行为,不需要数字符合词法公约。这也应该(隐式)支持INF 和NAN。 Lexical Conventions 中的文本进行了类似的修改,以允许使用带有 0x 前缀的十六进制常量。
这不会像gawk 中所希望的那样(考虑到对数字的词法约束):
$ echo "0x14" | gawk '$1+1<=0x15 {print $1+1}'
1
(注意“错误”的数字答案,它会被 |wc -l 隐藏)
除非你也使用--non-decimal-data:
$ echo "0x14" | gawk --non-decimal-data '$1+1<=0x15 {print $1+1}'
21
另见:
此SE question 的已接受答案具有可移植性解决方法。
对非十进制数提供两种类型的支持的选项是:
- 仅使用
gawk,不使用 --posix 和使用 --non-numeric-data
- 实现一个包装函数来执行十六进制转十进制,并将其与您的文字和输入数据一起使用
如果您搜索“awk dec2hex”,您可以找到许多后者的实例,一个可以通过的实例在这里:http://www.tek-tips.com/viewthread.cfm?qid=1352504。如果你想要像 gawk 的 strtonum() 这样的东西,你可以得到一个可移植的 awk-only 版本 here。