防止 awk 将以 0 开头的字符串转换为 oct

Prevent awk from converting string starting with 0 to oct

这个让我睡了一夜。

假设你有一个文件a_file.txt如下。

1000    JUC_0000    1
2494    JUC_AAAA    2
2495    JUC_BBBB1   3
2495    JUC_BBBB2   4
4676    JUC_CCCC    5
4677    JUC_DDDD1   6
4677    JUC_DDDD2   7

如果你运行

awk '{if(==4677){print [=11=];}}' a_file.txt

如你所愿:

4677    JUC_DDDD1   6
4677    JUC_DDDD2   7

但是,如果您 运行

awk '{if(==04677){print [=13=];}}' a_file.txt

你可能(我)很惊讶得到

2495    JUC_BBBB1   3
2495    JUC_BBBB2   4

似乎发生的是 awk 将 04677 解释为 2495 的八进制表示,并 运行s 与它一起。

两个问题:

  1. 我对结果的解读是否正确?
  2. 有没有办法阻止 awk 将以 0 开头的数字解释为八进制数并改为使用它们的十进制解释?
  3. gawk 是否具有相同的行为,是否可以更改它?
  1. 以零开头的数字是 awk 中的 octal 个数字。 2495 是八进制数 4677.

  2. 的十进制值
  3. 没有以 0 开头的小数 - 除了 0 本身。

  4. 是的,不会变。


顺便说一句,

的概念化版本
awk '{if(==4677){print [=10=];}}' file

awk '==4677' file

我可以建议两个备选方案,您可以通过引用您要查找的密钥来进行字符串匹配,这样“04677”将不会匹配。

$ awk '=="04677"' file

或者,如果您知道您的密钥是数字,您可以添加零以转换为十进制

$ awk '==04677+0' file

当您写 ==04677 而不是 ==4677 时,您 告诉 awk 将 04677 视为八进制数,就像您写 ==0x4677 你会告诉 awk 把它当作十六进制,而 ==4677"" 你会告诉 awk 把它当作字符串。如果你不想要这些,那就不要那样做。

更新: 根据您在 下发表的评论:

The problem arose from running awk within a script where the key 04677 was a string but the file had a numeric first column (no leading zeros). The "04677" option would not work, because the string on the file does not contain the leading 0. I had thought this would not matter if I left it numeric, but the octal conversion caught me off guard. I believe the 04677+0 option would work well in this case.

您刚才在该评论中描述的是一个与您在问题中所述完全不同的问题。现在您不再将十进制与八进制进行比较,而是将数字与字符串进行比较,并且在这种情况下使用的操作是字符串比较(请参阅 https://www.gnu.org/software/gawk/manual/gawk.html#Typing-and-Comparison)所以 4677 != "04677" 因为 4677 的第一个字符是 "4"04677 的第一个字符是 "0"。它与数字的八进制表示完全无关。是的,使用 "04677"+0 会起作用,因为它将字符串转换为数字 (4677),因此您最终得到的是数字而非字符串比较。