【问题标题】:Unwanted zeros in AWK outputAWK 输出中不需要的零
【发布时间】:2015-01-15 19:24:07
【问题描述】:

问题说明

在 Ubuntu 上使用 bash,我使用 java prog 通过串行(它连接到无线基站)连续读取一些数据包,并将其通过 cut 和 @987654323 管道传输@ 得到结果。我使用unbuffer 实时查看输出(否则输出等到缓冲区满)。

我在终端上发出的命令的语法:

java prog | unbuffer -p process1 | unbuffer -p process2

我发出的实际命令:

java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:telosb |
unbuffer -p cut -c49-50,52-53,55-56,58-59,60,61-62,64-65,67-68,70-71,72,73-74,76-77,79-80,82-83 |
unbuffer -p awk -F " " '{printf("%d %5.4f %5.4f\n",("0x"$1)*1,("0x"$2)*2*0.0005714,("0x"$3)/612500)}'

我的输出:

43301 1.9370 5.0124
0 0.0000 0.0000
43303 1.9279 5.0071
0 0.0000 0.0000
43305 1.9428 5.0125
0 0.0000 0.0000
43306 1.9428 5.0072
0 0.0000 0.0000
. 
.
.

零线不是真实的而是虚假的。如果我只执行java prog(即cut之前)或java prog + process1(即AWK之前),它们不会出现。它们仅在 process2 之后出现在输出中,在使用 awk 之后。

我想要什么

我想找出为什么我的输出中有零以及如何。

感谢您的帮助。谢谢。


补充数据

其中一个接收到的数据包看起来像这样(在java prog之后输出)。都是hex(现阶段未分组):

 00 FF FF 00 01 1C 22 95 00 00 00 00 00 00 00 00 00 00 25 83 00 00 06 95 00 2E BF 60 00 2E C0 BB 00 00 00 00

在上面,看起来所有数字都是两个一组。但是里面有数字集群——因此我cut它们的方式是我相应地重新组合它们。 cut之后的输出如下:

java prog + process1之后的输出

0000A995 00000697 002EBE00
0000A998 0000069F 002EE4FB
0000A99C 000006A4 002EBF9F
0000B421 000006A4 002ECC6B
 .
 .
 .

注意:这两个输出不是它们自己的转换。它们是在不同的情况下拍摄的,只是为了提供一个例子。

【问题讨论】:

  • 输出行尾随空格 — ick.
  • @JonathanLeffler 我检查了。输出行中没有任何尾随空格。
  • 那么请显示您的实际代码,因为"%d \n" 在换行符之前强制使用空格。

标签: linux bash awk terminal cut


【解决方案1】:

您正在使用printf("%d \n","0x"$1),即printf 期望一个数字是Ox$1 的值。因此,当它不是数字时,awk 会打印出0

您可能想改用%s,以便打印一个字符串。

看一个例子:

$ awk 'BEGIN {printf("%d \n","0xAA")}'
0 
$ awk 'BEGIN {printf("%s \n","0xAA")}'
0xAA 

您可以在 awk 手册中看到 printf 的格式控制字母的完整列表:http://www.gnu.org/software/gawk/manual/gawk.html#Control-Letters

关于 awk 和 gawk 中的十六进制值的有趣阅读:http://www.delorie.com/gnu/docs/gawk/gawk_77.html

【讨论】:

  • @mlomailom 那么看看每个数字如何映射到输出会很有趣。我猜0000236B 映射到9192 等等,但我认为逻辑不够清楚。如果你能在cutawk之前提供一个清晰的输入样本就好了,因为看起来printf的数据确实有些问题。
  • @mlomailom:我错过了什么吗?我在awk 'BEGIN { d = 0xAA; printf("%d\n", d); }' 上尝试了许多变体,但无法让awk 识别十六进制常量,这让我很惊讶。它每次都将其视为0。这是在带有 BSD awk 的 Mac 上。 […时间过去…] 当我用gawk (GNU awk) 尝试它时,它立即按我预期的那样工作。那么,您使用的awk 版本是否存在问题?
  • @mlomailom: awk 在字符串和数字之间切换相当容易。 'd = "AA"; printf("%d\n", "0x"d); 代码与 BSD awk 一起使用,产生 170。您可能需要使用 $1""$1 转换为字符串;您可以经常使用$1+0 将其转换为数字。我认为您已经获得了解决问题所需的信息,但我还没有将它们整合到统一的答案中。我不知道 BSD awk 不支持十六进制常量;我学到了一些东西。有时,我需要检查 POSIX 规范,看看它是否只是一个错误(感觉应该是这样)。
  • @JonathanLeffler 对此有一个有趣的答案:How to make calculations on hexadecimal numbers with awk?
  • 我安装了gawk。然后我的输出都是0!我将命令更改为:java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:telosb | unbuffer -p cut -c49-50,52-53,55-56,58-59,60,61-62,64-65,67-68,70-71,72,73-74,76-77,79-80,82-83 | gawk -F " " --non-decimal-data '{printf("%d\t%5.4f\t%5.4f\t\n","0x"$1,("0x"$2)*2*0.0005714,("0x"$3)/612500)}'。仅更改为 gawk 而不是 awk--non-decimal-data。然后我想要的输出再次出现,零点消失了。谢谢@JonathanLeffler。感谢@fedorqui 最后的评论和链接!
【解决方案2】:

所以,我回答我的问题的灵感来自我得到的答案 + 伟大的 cmets 和帮助花絮。

问题

使用awk。没有安装gawk

命令:

 java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:telosb |
 unbuffer -p cut -c49-50,52-53,55-56,58-59,60,61-62,64-65,67-68,70-71,72,73-74,76-77,79-80,82-83|
 unbuffer -p awk -F " " '{printf("%d\t%5.4f\t%5.4f\t\n","0x"$1,("0x"$2)*2*0.0005714,("0x"$3)/612500)}'

输出:

 2723   1.9233  5.0164  
 0  0.0000  0.0000  
 2726   1.9268  5.0164  
 0  0.0000  0.0000  
 2730   1.9428  5.0073  
 0  0.0000  0.0000  
 2732   1.9348  4.9866  
 0  0.0000  0.0000
 .
 .
 .

零是不可取的。

解决方案

已安装gawk。使用它,我将命令更改如下:

命令:

 java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:telosb |
 unbuffer -p cut -c49-50,52-53,55-56,58-59,60,61-62,64-65,67-68,70-71,72,73-74,76-77,79-80,82-83|
 gawk -F " " --non-decimal-data '{printf("%d\t%5.4f\t%5.4f\t\n","0x"$1,("0x"$2)*2*0.0005714,("0x"$3)/612500)}'

输出:

 2723   1.9233  5.0164  
 2726   1.9268  5.0164  
 2730   1.9428  5.0073  
 2732   1.9348  4.9866  
 .
 .
 .

零已经消失了。唯一的变化是 gawk 而不是 awk,添加了 --non-decimal-data 选项,并删除了 unbuffer -p

注意:当我打开 unbuffer -p 时,零会重新出现。深思熟虑。也许,以后有人可以处理。

【讨论】:

  • 太棒了!所以这是awk / gawk 以及它如何处理数字的问题。
  • @fedorqui 我怀疑这也是关于unbuffer。当我在上面的解决方案中添加另一个管道(将输出写入文件)时,零重新启动!所以,受够了unbuffer,我在除第一个进程之外的每个进程(进行行缓冲)开始时都使用了stdbuf -oL。现在一切正常。如果没有深入了解 unbufferpipe 的工作原理,我无法详细解释这个问题。 核心问题仍然是个谜,但是表面问题已经解决了:)谢谢你们。
猜你喜欢
  • 2012-04-11
  • 1970-01-01
  • 2022-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
  • 1970-01-01
相关资源
最近更新 更多