per*_*xed 9 command-line pipe sed
我在串行端口有一个传入流,新行大约每秒出现一次
wren@Raven:~$ cat /dev/ttyUSB0
A_Sensor1,B_22.00,C_50.00
A_Sensor1,B_22.00,C_50.00
A_Sensor1,B_22.00,C_50.00
A_Sensor1,B_22.00,C_50.00
A_Sensor1,B_22.00,C_50.00
Run Code Online (Sandbox Code Playgroud)
我想去除空行并对其余部分进行时间戳。
sed 将剔除空行并添加时间戳,但我无法更新时间戳,它只报告调用它的时间:
wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' -e "s/$/`date +\,%F\,%T`/"
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
A_Sensor1,B_22.00,C_50.00,2014-05-14,09:44:42
^C
Run Code Online (Sandbox Code Playgroud)
我找到了 ts,Moreutils 的一部分,并且可以通过管道输入它以获得更新时间戳。
wren@Raven:~$ cat /dev/ttyUSB0 | ts
May 14 09:49:26 A_Sensor1,B_22.00,C_50.00
May 14 09:49:26
May 14 09:49:27 A_Sensor1,B_22.00,C_50.00
^C
Run Code Online (Sandbox Code Playgroud)
但是,我无法将 ts 与 sed 正确结合。
这看起来应该做我想做的事,根本不产生任何输出
wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' | ts
^C
wren@Raven:~$
Run Code Online (Sandbox Code Playgroud)
然而,颠倒管道的顺序确实会产生输出,但当然不会去除不再空白的线条。其他替换工作正常,所以我知道 sed 的管道正在工作。
wren@Raven:~$ cat /dev/ttyUSB0 | ts | sed -e '/^$/d'
May 14 10:07:25 A_Sensor1,B_22.00,C_50.00
May 14 10:07:25
May 14 10:07:26 A_Sensor1,B_22.00,C_50.00
May 14 10:07:26
^C
Run Code Online (Sandbox Code Playgroud)
所以我有点困惑。我大概可以让 sed 删除不需要的行,但是在删除之前给它们加上时间戳肯定是错误的方法。
我希望得到解释和一些帮助。
直接回答问题sed
是缓冲,这是唯一的问题。
您可以通过告诉它不要使用其-u
/--unbuffered
标志进行缓冲来解决此问题:
sed -u '/^$/d' /dev/ttyUSB0 | ts
Run Code Online (Sandbox Code Playgroud)
使用测试工具(但您需要运行它来证明):
$ (echo -e 'banana\n\n'; sleep 2; echo 'cheese') | sed -u '/^$/d' | ts
May 14 11:26:05 banana
May 14 11:26:07 cheese
Run Code Online (Sandbox Code Playgroud)
您可能会遇到与其他流编辑器类似的困境。他们似乎都想缓冲一点。不过,他们都有解决方法。这是我测试过的一堆命令:
... | mawk -W interactive '/./' | ts
... | gawk '/./ { print $0; fflush(); }' | ts
... | grep --line-buffered '.' | ts
... | perl -n -e 'print if /./' | ts
Run Code Online (Sandbox Code Playgroud)
另一个想法是让gawk
处理它。它可以过滤非空行并为您打印日期(感谢 SO 的Kieron):
awk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' /dev/ttyUSB0
Run Code Online (Sandbox Code Playgroud)
行进来后直接刷新。gawk
如果你想做其他事情,这里特别有用......如果你想检查输出的第四列(pre- ts
)是否与正则表达式匹配,你可以(例如$4~/\d{4}/
)。Awk(及其变体)对于流处理非常灵活。
另一个测试工具:
$ gawk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' <(
echo -e 'banana\n\n';
sleep 2;
echo 'cheese'
)
2014-05-14 11:13:59 banana
2014-05-14 11:14:01 cheese
Run Code Online (Sandbox Code Playgroud)