Передача по каналу с Moreutils ts

У меня есть входящий поток в последовательном порту с новыми строками, появляющимися о столь же в секунду

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 удалить нежелательные строки, но добавление метки времени к ним до удаления должно быть неправильным подходом.

Я ценил бы объяснение и некоторую справку.

9
задан 14 May 2014 в 14:07

2 ответа

Отвечать на вопрос непосредственно, 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 обработайте его. Это может отфильтровать для непустых строк и сделать печать даты для Вас (благодаря Kieron SO):

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

Это сбрасывает прямо после того, как строки входят. gawk особенно полезно здесь, если Вы хотите сделать другие вещи... Если Вы хотите проверить что четвертый столбец вывода (пред -ts) соответствует regex, Вы можете (например, $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
9
ответ дан 23 November 2019 в 05:04

удар может обработать это в 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
0
ответ дан 16 November 2019 в 16:21

Другие вопросы по тегам:

Похожие вопросы: