使用awk读取串口输入并插入日期

3
我正在尝试重新格式化串口输入,它由两个整数用逗号隔开组成(从Arduino发送)。
1,2
3,4
0,0
0,1

等等,您需要将日期添加到每行后面,并用制表符分隔所有内容。这是我目前的代码:

cat /dev/cu.usbmodem3d11 | awk 'BEGIN {RS=","};{printf "%i\t%i\t%s",$1,$2,system("date")}'

这是我得到的结果(包含我的当地日期):
1   2   0Mer 26 fév 2014 22:09:20 EST
3   4   0Mer 26 fév 2014 22:09:20 EST
0   0   0Mer 26 fév 2014 22:09:20 EST
0   1   0Mer 26 fév 2014 22:09:20 EST

为什么我的日期字段前面会多出一个“0”?抱歉,我是新手,不太懂。

编辑 这段代码解决了我的问题。感谢所有帮助过我的人。

awk 'BEGIN {FS=","};{system("date")|getline myDate;printf "%i\t%i\t%s",$1, $2, myDate}' /dev/cu.usbmodem3d11

我不清楚原因,但为了让日期持续更新并记录接收数据的时间,我必须在上述代码中使用 system("date") 而不是仅使用 "date"


1
你应该尽量避免在可以自行读取文件的程序中使用cat,比如awk。例如:awk 'code' /dev/cu.usbmodem3d11 - Jotne
有使用 awk 的特别原因吗?你可以很容易地在纯 shell(bash 或 posix)中完成这个任务,而不需要调用其他语言解释器。 - ghoti
@Jotne 很好的建议,我会相应地更新。 - timtom
3个回答

2

2件事情

如果在你的printf字符串末尾添加一个\n,那么你的问题会更容易被看到。

然后输出将是:

>echo '1,2' | awk 'BEGIN {RS=","};{printf "%i\t%i\t%s\n",$1,$2,system("date")}'
Wed Feb 26 21:30:17 CST 2014
1       0       0
Wed Feb 26 21:30:17 CST 2014
2       0       0

我猜测system("date")命令的输出是在awk的每行输入处理的$0自然范围之外。其他人可能能够提供更好的解释。 为了获得所需的输出,我使用getline函数将date命令的输出捕获到一个变量(myDt)中。现在输出是:
> echo '1,2' | awk 'BEGIN {RS=","};{"date" | getline myDt ; printf "%i\t%i\t%s\n",$1,$2,myDt}'
1       0       Wed Feb 26 21:31:15 CST 2014

2       0       Wed Feb 26 21:31:15 CST 2014

最后,我们删除了“调试”\n字符,并获得了您指定的输出。
> echo '1,2' | awk 'BEGIN {RS=","};{"date" | getline myDt ; printf "%i\t%i\t%s",$1,$2,myDt}'
1       0       Wed Feb 26 21:34:56 CST 2014
2       0       Wed Feb 26 21:34:56 CST 2014

根据Jaypal的帖子,我现在明白FS=","是另一个问题,因此当我们进行更改并返回`\n'字符时,我们有以下结果:

echo '1,2' | awk 'BEGIN {FS=","};{"date" | getline myDt ; printf "%i\t%i\t%s\n",$1,$2,myDt}'
1       2       Wed Feb 26 21:44:42 CST 2014

谢谢您的帮助。然而,使用这段代码日期也没有增加(请参见其他解决方案中用户gothi的其他评论)。我猜测是因为“date”| getline命令只执行了一次。 - timtom
只想澄清一下,我需要日期反映数据被读取时的时间(从串口流式传输)。 - timtom
通过使用原始代码,日期永远不会更新。相反,使用 system("date") | getline myDt,日期将被更新。 - timtom
我期望 "date"| getline myDt 可以适用于读取的每一行数据。我现在没有时间测试它。你让它运行了一段时间吗?你仍然得到相同的日期吗?如果是这样,那么谢谢你的分享!无论如何,我很高兴能够帮助。祝大家好运。 - shellter

2

两个问题:

第一个 - RS 是记录分隔符。你需要使用字段分隔符 FS 来分隔两列,其中 $1 将是 1$2 将是 2(根据您的第一行)。

第二个 - 输出中多余的 0system() 命令的返回值。它表示命令成功运行。你可以直接在引号中运行 shell 命令并将其管道输出到 getline。在其后放置一个变量将允许你捕获返回的值。

试试这个:

 awk 'BEGIN {FS=","};{"date"|getline var;printf "%i\t%i\t%s\n",$1,$2,var}'

同样的问题,日期没有增加。 - timtom
通过使用原始代码,日期永远不会更新。相反,使用system("date") | getline var,日期将被更新。 - timtom

0

这是一个更简单的解决方案:

awk -F, '{print $1,$2,dt}' dt="$(date)" OFS="\t" /dev/cu.usbmodem3d11
1       2       Thu Feb 27 06:23:41 CET 2014
3       4       Thu Feb 27 06:23:41 CET 2014
0       0       Thu Feb 27 06:23:41 CET 2014
0       1       Thu Feb 27 06:23:41 CET 2014

如果你想以其他格式显示日期,只需查阅《date》手册即可。 例如:dt="$(date +%D)"会得到02/27/14

1
这个命令不是只在 awk 第一次运行时运行 date 命令吗?如果在 tail -f 上运行,日期将永远不会改变。 - ghoti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接