使用Moreutils ts进行配管


9

我的串行端口有输入流,新行大约每秒出现一次

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

我想去除空白行并为其余部分加时间戳。

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

我找到了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

但是,我无法将ts与sed正确组合。

这看起来像它应该做我想要的,根本不产生任何输出

wren@Raven:~$ cat /dev/ttyUSB0 | sed -e '/^$/d' | ts
^C
wren@Raven:~$

但是,颠倒管道的顺序确实会产生输出,但是当然不会去除不再为空白的线。其他替换工作正常,因此我知道要进行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

所以我有点困惑。我大概可以使sed删除不需要的行,但是在删除之前加上时间戳记肯定是错误的方法。

我将不胜感激,并提供一些帮助。

Answers:


9

要直接回答这个问题,sed就是缓冲,这是唯一的问题。
您可以通过告诉它不要使用-u/ --unbuffered标志来进行缓冲来解决此问题:

sed -u '/^$/d' /dev/ttyUSB0 | ts

使用测试工具(但是您需要运行以进行证明):

$ (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

您可能会遇到与其他流编辑器类似的困境。他们似乎都想缓冲一点。他们都有解决方法。这是我测试过的一堆命令:

... | mawk -W interactive '/./' | ts
... | gawk '/./ { print $0; fflush(); }' | ts
... | grep --line-buffered '.' | ts
... | perl -n -e 'print if /./' | ts

另一个想法是让它gawk处理。它可以过滤非空行并为您进行日期打印(这要归功于SO的Kieron):

awk '/./ { print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' /dev/ttyUSB0

插入行后立即刷新。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

1
为+1 sed -u。这是块缓冲与行缓冲的问题。
jfs 2014年

@Oli sed -u在通过管道传输到ts时也可以完美工作,因此我将继续阅读有关缓冲的内容。我不再困惑,非常感谢。
2014年

awk特别适合这种情况。与sed相比,awk代码通常不那么密集,可读性也更高,并且您可以在调试时根据需要查看的部分结果中插入尽可能多的打印语句。您可以将整个awk程序放入here文档中,以避免使用单独的文件,并且如果在here文档终止符字符串两边加上引号,则bash将忽略通常尝试解释的所有嵌入式标记。

0

bash可以while read循环处理

(echo -e 'banana\n\n'; sleep 2; echo 'cheese') | 
while IFS= read -r line; do 
    [[ $line ]] && echo "$(date "+%F %T") line"
done
2014-05-14 06:34:06 banana
2014-05-14 06:34:08 cheese

您可以使用棘手的参数扩展来删除仅包含空格的行:删除所有前导空格并查看行是否为空:

shopt -s extglob

(echo -e '  banana\n\t\n'; sleep 2; echo 'cheese') |
while IFS= read -r line; do
    [[ "${line/#+([[:blank:]])/}" ]] && echo "$(date "+%F %T") $line"
done

我尝试了各种各样的方法,但没有一个起作用。我也无法使您的代码正常工作。使用echo或cat将/ dev / ttyUSB0发送到while循环只会导致一行输出:2014-05-14 12:23:32 line
困惑的

我敢肯定有更好的方法,但是请尝试tail -f /dev/ttyUSB0代替cat或echo。它将继续运行。我不知道如何在我的系统上进行测试。
2014年

tail -f / dev / ttyUSB0不提供输出,带或不带while循环。电视为您的意见。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.