मोरुटिल्स टीएस के साथ पाइपिंग


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:~$

हालाँकि, पाइप के क्रम को उलट देने से आउटपुट उत्पन्न होता है, लेकिन निश्चित रूप से उन लाइनों को नहीं खींचता है जो अब खाली नहीं हैं। अन्य प्रतिस्थापन ठीक काम करते हैं, इसलिए मुझे पता है कि सेड तक पाइप काम कर रहा है।

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

सीधे सवाल का जवाब देने के लिए, 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

आप अन्य स्ट्रीम संपादकों के साथ समान विधेयकों में भाग सकते हैं। वे प्रतीत होता है कि सभी थोड़ा सा बफर करना चाहते हैं। वे सभी हालांकि workarounds है। यहाँ उन कमांडों का एक गुच्छा है जो मैंने परीक्षण किया है:

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

एक और विचार सिर्फ इसे gawkसंभालने के लिए है। यह गैर-खाली लाइनों के लिए फ़िल्टर कर सकता है और आपके लिए दिनांक-मुद्रण कर सकता है (एसओ के किरोन के लिए धन्यवाद ):

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

लाइनों में आने के बाद यह सीधे फ्लश हो जाता है। gawkविशेष रूप से यहाँ उपयोगी है यदि आप अन्य काम करना चाहते हैं ... यदि आप यह जाँचना चाहते हैं कि आउटपुट का चौथा स्तंभ 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

@ ओली sed-t भी पूरी तरह से काम करता है जब ts में पाइप किया जाता है, तो मैं बफरिंग के बारे में पढ़ूंगा। मैं अब चकित नहीं हूं, बहुत धन्यवाद।
हैरान

awk इस तरह की चीजों के लिए विशेष रूप से अनुकूल है। awk कोड आम तौर पर बहुत कम घने और बहुत अधिक पठनीय होता है और आप डीबगिंग करते समय आंशिक परिणाम देखना चाहते हैं और आप जितने प्रिंट स्टेटमेंट में फेंक सकते हैं। आप एक अलग फ़ाइल का उपयोग करने से बचने के लिए एक संपूर्ण दस्तावेज़ यहाँ एक दस्तावेज़ में रख सकते हैं और यदि आप यहाँ दस्तावेज़ टर्मिनेटर स्ट्रिंग के चारों ओर उद्धरण डालते हैं, तो बैश उन सभी एम्बेडेड टोकन को अनदेखा कर देगा जो सामान्य रूप से व्याख्या करने की कोशिश करेंगे।
जो

0

बैश एक 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

मैंने इस तरह के विभिन्न तरीकों की कोशिश की, उनमें से किसी ने भी काम नहीं किया। मुझे आपका कोड काम करने के लिए नहीं मिल रहा है। गूंज या बिल्ली का उपयोग भेजने के लिए / dev / ttyUSB0 जबकि पाश सिर्फ उत्पादन की एक पंक्ति में जो परिणाम के लिए: 2014-05-14 12:23:32 लाइन
हैरान

मुझे यकीन है कि एक बेहतर तरीका है, लेकिन tail -f /dev/ttyUSB0बिल्ली या गूंज के बजाय कोशिश करें । यह चलता रहेगा। मुझे नहीं पता था कि मेरे सिस्टम पर यह परीक्षण कैसे किया जाता है।
जो

टेल -f / dev / ttyUSB0 लूप के साथ या उसके बिना कोई आउटपुट नहीं देता है। आपकी टिप्पणियों के लिए टी.वी.
हैरान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.