防止 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 与它一起。
两个问题:
- 我对结果的解读是否正确?
- 有没有办法阻止 awk 将以 0 开头的数字解释为八进制数并改为使用它们的十进制解释?
- gawk 是否具有相同的行为,是否可以更改它?
以零开头的数字是 awk
中的 octal
个数字。 2495
是八进制数 4677
.
的十进制值
没有以 0
开头的小数 - 除了 0
本身。
是的,不会变。
顺便说一句,
的概念化版本
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
),因此您最终得到的是数字而非字符串比较。
这个让我睡了一夜。
假设你有一个文件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 与它一起。
两个问题:
- 我对结果的解读是否正确?
- 有没有办法阻止 awk 将以 0 开头的数字解释为八进制数并改为使用它们的十进制解释?
- gawk 是否具有相同的行为,是否可以更改它?
以零开头的数字是
awk
中的octal
个数字。2495
是八进制数4677
. 的十进制值
没有以
0
开头的小数 - 除了0
本身。是的,不会变。
顺便说一句,
的概念化版本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
),因此您最终得到的是数字而非字符串比较。