लगातार स्ट्रीमिंग आउटपुट में हेरफेर करने के लिए sed का उपयोग कैसे करें?


13

मैं गैर-तकनीकी दर्शकों के लिए एक प्रस्तुति दे रहा हूं। मेरे पास बैश में चलने वाला एक कार्यक्रम है जो मूल्यों की एक सतत धारा को आउटपुट करता है, जिनमें से कुछ महत्वपूर्ण हैं। मैं महत्वपूर्ण परिणामों को उजागर करना चाहूंगा क्योंकि वे प्रदर्शित किए जाते हैं ताकि दर्शकों को उनकी आवृत्ति का अंदाजा हो सके। मुद्दा यह है कि मैं sedएक रनिंग स्ट्रीम पर काम नहीं कर सकता । यह ठीक काम करता है अगर मैं एक फ़ाइल में परिणाम डालते हैं, जैसे:

cat output.txt | sed "s/some text/some text bolded/"

लेकिन अगर मैं रनिंग आउटपुट पर इसी तरह की कोशिश करता हूं, तो इस तरह:

command | sed "s/some text/some text bolded/"

sedकुछ नहीं करता। कोई विचार?

जैसा कि लैम्बर्ट इशारा करने में काफी मददगार थे, मेरा कहना है कि sedकुछ भी अस्पष्ट नहीं था। क्या हो रहा है कि प्रोग्राम आउटपुट करता है stdout(मुझे पूरा यकीन है कि यह लिखना नहीं है stderr) जैसा कि सामान्य रूप से होता है, भले ही इसके माध्यम से पाइप किया गया हो sed

समस्या यह प्रतीत होती है कि कमांड एक दूसरे प्रोग्राम को कॉल करता है, जो तब stdout को आउटपुट करता है। पहले कार्यक्रम द्वारा मुद्रित कुछ पंक्तियाँ हैं; ये मैं संपादित कर सकता हूं। फिर दूसरे कार्यक्रम द्वारा मुद्रित मूल्यों की एक धारा है; ये मैं संपादित नहीं कर सकता।

Perl और awk विधियाँ या तो काम नहीं करती हैं।


5
stdbuf -o0 command | sed "s/some text/some text bolded/"काम करता है ?
फ्लोइम स्वयं

3
'Sed कुछ नहीं करता है' से आपका मतलब है कि प्रतिस्थापन नहीं किया गया है, या आपके पास कोई आउटपुट नहीं है? कमांड stdout के बजाय stderr को लिख सकता है? यदि आप किसी ऐसी चीज को उजागर करना चाहते हैं जिसका आप उपयोग कर सकते हैंcommand|egrep 'some text|$'
लैम्बर्ट

क्या कमांड लेखन stdout (और stderr को नहीं) है?
एंथन

1
यह देखते हुए कि पाठ एक से अधिक बार दिखाई देता है, आपको एक g"वैश्विक" प्रतिस्थापन जोड़ना चाहिए , अन्यथा एक पंक्ति में केवल पहली घटना को प्रतिस्थापित किया जाएगा:sed "s/old/new/g"
ph0t0nix

@ ph0t0nix नहीं, यह मुद्दा नहीं है, लेकिन यह लाइन के नीचे एक मुद्दा रहा होगा। पारितोषिक के लिए धन्यवाद।
पी जोन्स

जवाबों:


12

संभावना है कि कमांड का आउटपुट बफर है। जब कमांड एक टर्मिनल को लिखता है, तो बफर को हर नईलाइन पर फ्लश किया जाता है, इसलिए आप इसे अपेक्षित दर पर प्रदर्शित होते हैं। जब कमांड एक पाइप को लिखता है, तो बफर तभी फ्लश हो जाता है जब वह कुछ किलोबाइट तक पहुंच जाता है, इसलिए यह बहुत पीछे हो जाता है। इस प्रकार मानक इनपुट / आउटपुट लाइब्रेरी का डिफ़ॉल्ट व्यवहार है।

अपने आउटपुट को बुफे नहीं करने के लिए कमांड को मजबूर करने के लिए, आप unbuffer(उम्मीद से) या stdbuf(GNU कोरुटिल्स से ) उपयोग कर सकते हैं ।

unbuffer command | sed …
stdbuf -o0 command | sed …

stdbufकाम नहीं किया (यह पहले उल्लेख किया गया था, BTW), लेकिन unbufferकिया !! आपको पता नहीं है कि आपने मुझे कितना खुश किया है।
पी जोन्स

और संक्षिप्त स्पष्टीकरण के लिए धन्यवाद। बहुत मददगार।
पी जोन्स

sedस्वयं इस तरह के बफर का उपयोग करता है, (cf चेन्नीस्टार पोस्ट) इसलिए यहां के उदाहरण काम नहीं कर सकते क्योंकि अनबफर करने sedके commandलिए है: cat /etc/passwd | unbuffer sedलेकिन sedखुद के पास एक -uविकल्प है, इसलिए grepइस उदाहरण में अधिक उपयुक्त हो सकता है। आपकी पृष्ठभूमि की जानकारी के लिए बहुत बहुत धन्यवाद! बहुत बढ़िया जवाब!
गणित

4

sed उसके लिए एक विकल्प है:

-उ, - ऊँघना

जो इनपुट फाइलों से न्यूनतम मात्रा में डेटा लोड करता है और आउटपुट बफ़र्स को अधिक बार फ्लश करता है। man sedअधिक जानकारी के लिए देखें।


1
sedकेवल GNU (BSD नहीं sed), और मेरा मानना ​​है कि यह अभी भी पाइप के शुरू में कमांड के बफरिंग को नहीं रोकेगा। लेकिन यह उल्लेख करने के लिए अच्छा है। :)
वाइल्डकार्ड

stdbuf manpage में कहा गया है कि "यदि COMMAND अपनी मानक धाराओं (उदाहरण के लिए 'टी' करता है) के बफरिंग को समायोजित करता है, तो वह 'stdbuf' द्वारा संबंधित परिवर्तनों को ओवरराइड कर देगा।" ऐसा लग रहा है कि सेड इस श्रेणी में आ सकता है, लेकिन '-यू' ध्वज इसे असंबद्ध पाइप श्रृंखला में उपयोगी बना देगा।
मैटस्मिथ

2

मैं awk का उपयोग करता हूँ

  command | awk '/some important stuff/ { printf "%c[31m%s%c[0m\n",27,$0,27 ; next }
  { print ; } '

कहाँ पे

  • /some important stuff/ सेड की तरह महत्वपूर्ण लाइन का चयन करें
  • printf "%c[31m%s%c[0m\n",27,$0,27 ; लाल रंग में प्रिंट करें
    • हरे, पीले के लिए 32,33 का उपयोग करें ...
    • $ 1, $ 2, एक विशिष्ट क्षेत्र का चयन करने के लिए उपयोग किया जा सकता है
  • अन्य पंक्ति सिर्फ 'जैसा है' मुद्रित है

मुख्य बिंदु यह है कि commandलाइनों को फ्लश किया जाना चाहिए, लेकिन यदि आपके पास बहुत अधिक आउटपुट है तो यह मामला होना चाहिए।


नोट: प्रश्न यह नहीं कहता है कि पूरी लाइन "बोल्ड" होनी चाहिए, लेकिन सिर्फ "कुछ पाठ"। जबकि इस आदिम प्रतिस्थापन के मामले में उस सुविधा का awkउपयोग करना (उपयोग करना sub()या करना gsub()) sedनिश्चित रूप से उपयुक्त उपकरण है।
Janis

1

पर्ल रास्ता:

command | perl -pe 's/(stuff)/\x1b[1m$1\x1b[0m/g'

या एक निरंतर उत्पादन के साथ:

आउटपुट के लिए एक बैश स्क्रिप्ट cont:

#!/bin/bash
while [ true ]
do
   echo "Some stuff"
done

इसके साथ टेस्ट करें:

./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
  • \x1b[1m - बोल्ड या बढ़ी हुई तीव्रता
  • ${1} - बैकरेफेरेंज़
  • \x1b[0m - सभी विशेषताओं को रीसेट करें

आउटपुट:

कुछ सामान
कुछ सामान
कुछ सामान
कुछ सामान

अधिक भागने यहाँ कोड ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.