awk模式中的十六进制文字

She*_*tJS 4 unix macos awk

awk能够将字段解析为十六进制数字:

$ echo "0x14" | awk '{print $1+1}'
21 <-- correct, since 0x14 == 20
Run Code Online (Sandbox Code Playgroud)

但是,它似乎不处理十六进制文字的操作:

$ echo "0x14" | awk '$1+1<=21 {print $1+1}' | wc -l
1 <-- correct
$ echo "0x14" | awk '$1+1<=0x15 {print $1+1}' | wc -l
0 <-- incorrect.  awk is not properly handling the 0x15 here
Run Code Online (Sandbox Code Playgroud)

有解决方法吗?

mr.*_*tic 5

你在这里处理两个相似但不同的问题,awk输入中的非十进制数据和程序中的非十进制文字awk.

请参阅POSIX-1.2004 awk规范,词汇约定:

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', [...]
Run Code Online (Sandbox Code Playgroud)

所以awk(可能是你正在使用nawkmawk)表现得"正确".gawk(从版本3.1开始)默认情况下支持非十进制(八进制和十六进制)文字数字,但使用--posix开关会将其关闭,如预期的那样.

这种情况下的正常解决方法是使用定义的数字字符串行为,其中数字字符串有效地被解析为C标准atof()strtod()函数,它支持0x-prefixed数字:

$ echo "0x14" | nawk '$1+1<=0x15 {print $1+1}'
<no output>
$ echo "0x14" | nawk '$1+1<=("0x15"+0) {print $1+1}'
21
Run Code Online (Sandbox Code Playgroud)

这里的问题是,这不太正确,因为POSIX-1.2004还指出:

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
Run Code Online (Sandbox Code Playgroud)

更新:gawk针对"2008 POSIX.1003.1",但请注意,自2008版(参见此处IEEE Std 1003.1 2013版awk)允许strtod()和依赖于实现的行为不需要数字符合词汇约定.这应该(隐含的)支持INFNAN太.类似地修改了词汇约定中的文本,以选择性地允许带0x前缀的十六进制常量.

这将不会表现出(考虑到对数字的词汇限制),gawk如下所示:

$ echo "0x14" | gawk  '$1+1<=0x15 {print $1+1}'
1
Run Code Online (Sandbox Code Playgroud)

(注意是"错误"的数字答案,这将被隐藏的|wc -l),除非你使用--non-decimal-data过:

$ echo "0x14" | gawk --non-decimal-data '$1+1<=0x15 {print $1+1}'
21
Run Code Online (Sandbox Code Playgroud)

也可以看看:

这个SE问题的接受答案有一个可移植性解决方法.

对非十进制数具有两种类型支持的选项是:

  • 仅使用gawk,不使用--posix和使用--non-numeric-data
  • 实现一个包装器函数来执行十六进制到十进制,并将它与文字和输入数据一起使用

如果您搜索"awk dec2hex",您可以找到后者的许多实例,这里有一个可通过的实例:http://www.tek-tips.com/viewthread.cfm?qid = 1352504 .如果你想要像gawk这样的东西strtonum(),你可以在这里获得一个便携式awk专用版本.