使用awk删除前导零会产生八进制结果

时间:2014-04-29 23:33:33

标签: bash shell awk

背景

我有一个简单的问题,这对我来说已经消耗了一天的大部分时间。简而言之,我试图使用awk从字符串中删除前导零。 然而,在大家将此标记为重复之前,问题不在于如何删除前导零(这只是我想要实现的结果)。另外,这是特别关于变量的读取;我很清楚输出操作的格式字符串。

问题

我的问题是:每当我尝试将给定变量强制转换为整数时,awk正在读取前导零并将输入数视为八进制字符串。我有一些简单的例子来演示以下行为:

$ echo "0012" | awk '{$1=$1+0}1'
10
$ echo "0012" | awk '{$1=+$1}1'
10
$ echo "0011" | awk '{print ($1 + 0)}'
9
$ echo "0000" | awk '{$1=$1+0}1'
0

现在,我已经看到许多解决方案提供了各种sed命令来“预处理”并删除前导零。不幸的是,对我来说完全有效的输入是0000,基于字符串的解决方案会折叠为空字符串。

问题

简而言之,如何强制awk将其读取的变量视为十进制,而不管前导零?

参考

How to delete all characters but the last

strip leading zeros in awk program

Removing Leading Zeros within awk file

更新

我在原帖中忘记提及的事情:我正在尝试将0000合并为一个0。此外,我理想的解决方案是awk - 只是因为我的环境很薄(在嵌入式Linux和桌面操作系统之间)。有问题的awk由BusyBox 1.18.1提供,但其他一切应该非常接近现代桌面版Linux。

1 个答案:

答案 0 :(得分:5)

使用busybox调用awk,似乎可以执行以下操作:

$ printf '%s\n' 0000 0011 0012 |
  busybox awk '{print ($1".")+0}'
0
11
12

Posix要求awk使用等效的strtod将数据值转换为数字,而我能找到的所有awk实现都会这样做,busybox awk除外。 (Busybox当然并不声称与Posix兼容,但它有时会在这种情况下具有侵略性的不兼容性。)所以{print $1 + 0}应该可以正常工作,但它并不适用于busybox awk的情况,它将允许输入数据中的十六进制或八进制整数。

在数字上附加.会强制将整数视为浮点数,并且对实际浮点数没有影响,因为strtod在遇到可以&的字符时才会停止#39;被解码为数字的一部分。当然,如果该字段不是完全数字,它也将无效,因此如果您希望将0017a之类的字段转换为17a(或甚至17),解决方案不适合你。

作为旁注,awk中字符串连接的优先级低于加法的优先级(并且高于比较运算符),因此括号实际上是必需的; awk会将print $1""+0解析为print $1(""+0),它会将{0}附加到字符串值$1。 GNU awk手册表明,除了琐碎的表达式之外,你应该总是将连接加上括号,这对我来说是个好建议。

此外,当我尝试对busybox awk的数字转换算法进行逆向工程时,我发现它将012e3视为整数10而不是12000. {{1}但是,12e3转换为12000。如果不是特殊的话,012.e3就没有任何意义。