Moreutils ts ile borulama


9

Seri bağlantı noktasında gelen bir akışım var, saniyede bir kez yeni çizgiler görünüyor

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

Boş satırları soymak ve kalanları zaman damgası almak istiyorum.

sed boş satırları cull ve zaman damgası ekleyecek, ancak zaman damgası güncelleme yapamıyorum, sadece çağrıldığı zamanı bildirir:

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

Ben ts, Moreutils bir parçası buldum ve bir güncelleme zaman damgası almak için içine boru olabilir.

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

Ancak, ts'i sed ile düzgün bir şekilde birleştiremiyorum.

İstediğimi yapması gerektiği gibi görünen bu, hiç çıktı üretmez

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

Bununla birlikte, boruların sırasını tersine çevirmek bir çıktı üretir, ancak elbette artık boş olmayan hatları soymaz. Diğer ikameler iyi çalışıyor, bu yüzden sed için borunun çalıştığını biliyorum.

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

Bu yüzden biraz şaşkınım. Muhtemelen istenmeyen satırları sed kaldırabilirsiniz, ancak kaldırmadan önce zaman damgası yanlış bir yaklaşım olmalıdır.

Bir açıklama ve yardım için minnettar olurum.

Yanıtlar:


9

Soruyu doğrudan cevaplamak sedarabelleğe almak ve tek sorun bu.
Bunu, -u/ --unbufferedflag ile arabelleğe alınmamasını söyleyerek düzeltebilirsiniz :

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

Bir test kayışıyla (ancak kanıt için çalıştırmanız gerekir):

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

Diğer akış düzenleyicileri ile benzer öngörülerle karşılaşabilirsiniz. Görünüşe göre hepsi biraz tamponlamak istiyor. Hepsi olsa geçici çözümler var. İşte test ettiğim komutlar:

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

Başka bir fikir sadece gawkhalletmektir. Boş olmayan satırları filtreleyebilir ve sizin için tarih baskısını yapabilir (SO's Kieron sayesinde ):

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

Hatlar geldikten hemen sonra kızarır. Başka şeyler gawkyapmak istiyorsanız burada özellikle yararlıdır ... Dördüncü çıktı sütununun (ön ) bir normal ifadeyle eşleştiğini kontrol etmek istiyorsanız, (örneğin ) yapabilirsiniz . Awk (ve varyantları) akış işleme için çok esnektir.ts$4~/\d{4}/

Başka bir test donanımı:

$ 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
İçin +1 sed -u. Bir blok arabelleğe alma ve satır arabelleğe alma sorunudur.
jfs

@Oli sed -u ts'ye bağlandığında da mükemmel çalışır, bu yüzden arabelleğe alma hakkında okurum. Artık şaşkın değilim, çok teşekkürler.
çapraşık

awk özellikle bu tür şeyler için çok uygundur. awk kodu genellikle sed'den çok daha az yoğun ve çok daha okunabilirdir ve hata ayıklama sırasında kısmi sonuçları görüntülemek istediğiniz kadar çok sayıda yazdırma ifadesi atayabilirsiniz. Ayrı bir dosya kullanmaktan kaçınmak için burada bir belgeye bütün bir awk programı koyabilirsiniz ve burada belge sonlandırıcı dizesinin etrafına tırnak koyarsanız, bash normalde yorumlamaya çalışacağı tüm gömülü simgeleri yok sayar.
Joe

0

bash bunu bir while readdöngüde halledebilir

(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

Yalnızca zor bir parametre genişletmesi olan boşluk içeren satırları kaldırabilirsiniz: tüm önde gelen boşlukları kaldırın ve satırın boş olup olmadığına bakın:

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

Böyle yaklaşımları denedim, hiçbiri işe yaramadı. Kodunuzu da çalıştıramıyorum. Yankı veya kedi kullanma göndermek için / dev / ttyUSB0 while döngüsü sadece çıkış tek bir satır ile sonuçlanan için: 2014/05/14 12:23:32 hat
şaşkın

Eminim daha iyi bir yol vardır, ancak tail -f /dev/ttyUSB0kedi veya yankı yerine deneyin . Çalışmaya devam edecek. Bunu sistemimde nasıl test edeceğimi bilmiyordum.
Joe

tail -f / dev / ttyUSB0, while döngüsü ile veya bu döngü olmadan çıktı vermez. tvm yorumlarınız için.
çapraşık
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.