Rohrleitungen mit Moreutils ts

9

Ich habe einen eingehenden Stream an einer seriellen Schnittstelle, wobei etwa einmal pro Sekunde neue Leitungen angezeigt werden

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

Ich möchte leere Zeilen entfernen und den Rest mit einem Zeitstempel versehen.

sed löscht leere Zeilen und fügt einen Zeitstempel hinzu, aber ich kann das Zeitstempel-Update nicht durchführen. Es gibt nur die Zeit an, zu der es aufgerufen wurde:

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

Ich habe ts gefunden, einen Teil von Moreutils, und kann ihn weiterleiten, um einen aktualisierten Zeitstempel zu erhalten.

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

Allerdings kann ich ts nicht richtig mit sed kombinieren.

Dies, was so aussieht, als ob es tun sollte, was ich will, erzeugt überhaupt keine Ausgabe

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

Das Umkehren der Reihenfolge der Rohre führt zwar zu einer Ausgabe, entfernt jedoch natürlich keine Linien, die nicht mehr leer sind. Andere Substitutionen funktionieren einwandfrei, daher weiß ich, dass das zu sedierende Rohr funktioniert.

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

Also bin ich ein bisschen verblüfft. Vermutlich kann ich sed dazu bringen, die unerwünschten Linien zu entfernen, aber das Zeitstempeln vor dem Entfernen muss der falsche Ansatz sein.

Ich würde mich über eine Erklärung und Hilfe freuen.

verwirrt
quelle

Antworten:

9

Die Frage direkt zu beantworten, sedist Pufferung und das ist das einzige Problem.
Sie können dies beheben, indem Sie ihm mitteilen, dass er nicht mit dem Flag -u/ puffern soll --unbuffered:

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

Mit einem Testgeschirr (aber Sie müssen es zum Beweis ausführen):

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

Sie können mit anderen Stream-Editoren auf ähnliche Probleme stoßen. Sie wollen anscheinend alle ein bisschen puffern. Sie alle haben jedoch Problemumgehungen. Hier sind einige Befehle, die ich getestet habe:

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

Eine andere Idee ist, einfach damit gawkumgehen zu lassen. Es kann nach nicht leeren Zeilen filtern und den Datumsdruck für Sie durchführen (dank Kieron von SO ):

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

Dies gawkwird hier besonders hilfreich, wenn Sie andere Dinge tun möchten ... Wenn Sie überprüfen möchten, ob die vierte Ausgabespalte (vor ts) mit einem regulären Ausdruck übereinstimmt, können Sie dies (z $4~/\d{4}/. B. ). Awk (und seine Varianten) sind sehr flexibel für die Stream-Verarbeitung.

Ein weiteres Testgeschirr:

$ 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
Oli
quelle
1
+1 für sed -u. Es handelt sich um ein Problem zwischen Blockpufferung und Zeilenpufferung.
JFS
@Oli sed -u funktioniert auch perfekt, wenn es in ts geleitet wird, also werde ich mich über das Puffern informieren. Ich bin nicht mehr verblüfft, vielen Dank.
ratlos
awk eignet sich besonders gut für solche Dinge. awk-Code ist im Allgemeinen viel weniger dicht und viel besser lesbar als sed, und Sie können beim Debuggen so viele Druckanweisungen eingeben, wie Sie Teilergebnisse anzeigen möchten. Sie können ein ganzes awk-Programm in ein Here-Dokument einfügen, um die Verwendung einer separaten Datei zu vermeiden. Wenn Sie die Abschlusszeichenfolge des Here-Dokuments in Anführungszeichen setzen, ignoriert bash alle eingebetteten Token, die normalerweise zu interpretieren versuchen.
Joe
0

Bash kann dies in einer while readSchleife behandeln

(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

Sie können Zeilen mit nur Leerzeichen mit einer kniffligen Parametererweiterung entfernen: Entfernen Sie alle führenden Leerzeichen und prüfen Sie, ob die Zeile leer ist:

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
Glenn Jackman
quelle
Ich habe verschiedene Ansätze ausprobiert, von denen keiner funktioniert hat. Ich kann Ihren Code auch nicht zum Laufen bringen. Die Verwendung von echo oder cat zum Senden von / dev / ttyUSB0 an die while-Schleife führt nur zu einer einzigen Ausgabezeile: 2014-05-14 12:23:32 Zeile
ratlos
Ich bin sicher, es gibt einen besseren Weg, aber versuchen Sie es tail -f /dev/ttyUSB0anstelle von Katze oder Echo. Es wird weiterlaufen. Ich wusste nicht, wie ich das auf meinem System testen sollte.
Joe
tail -f / dev / ttyUSB0 gibt keine Ausgabe mit oder ohne while-Schleife aus. tvm für deine Kommentare.
ratlos