2008-09-24 26 views
13

मुझे यकीन है कि पेर्ल, रूबी, बैश के साथ कुछ मामूली एक-लाइनर है जो मुझे लूप में कमांड चलाने देता है जब तक कि मैं stdout में कुछ स्ट्रिंग नहीं देखता, फिर रुक जाता हूं। आदर्श रूप से, मैं stdout को भी कैप्चर करना चाहता हूं, लेकिन यदि यह कंसोल करने जा रहा है, तो यह पर्याप्त हो सकता है।जब तक मैं stdout में कुछ स्ट्रिंग नहीं देखता तब तक मैं लूप में कमांड कैसे चला सकता हूं?

इस समय प्रश्न में विशेष पर्यावरण रेडहाट लिनक्स है लेकिन कभी-कभी मैक पर भी एक ही चीज़ की आवश्यकता होती है। तो कुछ, जेनेरिक और * निक्सी सबसे अच्छा होगा। विंडोज के बारे में परवाह नहीं है - शायद एक * निक्सी चीज साइगविन के तहत काम करेगी।

अद्यतन: ध्यान दें कि "कुछ स्ट्रिंग का निरीक्षण करें" मेरा मतलब है "stdout में कुछ स्ट्रिंग है" नहीं "stdout कुछ स्ट्रिंग है"।

उत्तर

13

पर्ल में:

#!/usr/local/bin/perl -w 

if (@ARGV != 2) 
{ 
    print "Usage: watchit.pl <cmd> <str>\n"; 
    exit(1); 
} 

$cmd = $ARGV[0]; 
$str = $ARGV[1]; 

while (1) 
{ 
    my $output = `$cmd`; 
    print $output; # or dump to file if desired 
    if ($output =~ /$str/) 
    { 
     exit(0); 
    } 
} 

उदाहरण:

[bash$] ./watchit.pl ls stop 
watchit.pl 
watchit.pl~ 
watchit.pl 
watchit.pl~ 
... # from another terminal type "touch stop" 
stop 
watchit.pl 
watchit.pl~ 

आप में एक सोने को जोड़ने के लिए है, हालांकि चाहते हो सकता है।

+0

से बहुत कम स्पष्ट है, मैंने इसे स्वीकार कर लिया क्योंकि ए) यह मेरे लिए तुरंत काम करता था और बी) यह आसान था कुछ चीजों को जोड़ने के लिए हैक करने के लिए (एक काउंटर, आदि)। लेकिन यहां कई अन्य समाधान भी अच्छे लगते हैं। –

10

ऐसा करने के तरीके, पहले जो मन में आया का एक समूह है था:

OUTPUT=""; 
while [ `echo $OUTPUT | grep -c somestring` = 0 ]; do 
    OUTPUT=`$cmd`; 
done 

$ cmd कहाँ निष्पादित करने के लिए अपने आदेश है।

की बिल्ली के लिए, यहाँ एक मार समारोह संस्करण है, तो यदि आप उसका एक नियमित आधार पर एक इंटरैक्टिव खोल से आह्वान करने के लिए इच्छुक रहे हैं आप और अधिक आसानी से इस कॉल कर सकते हैं:

function run_until() { 
    OUTPUT=""; 
    while [ `echo $OUTPUT | grep -c $2` = 0 ]; do 
    OUTPUT=`$1`; 
    echo $OUTPUT; 
    done 
} 

अस्वीकरण : केवल हल्के ढंग से परीक्षण किए जाने पर, कुछ अतिरिक्त भागने आदि की आवश्यकता हो सकती है यदि आपके आदेशों में बहुत से तर्क हैं या स्ट्रिंग में विशेष वर्ण हैं।

संपादित: एडम की टिप्पणी से प्रतिक्रिया के आधार पर - अगर आप के साथ, (यानी उत्पादन प्रदर्शित करने के लिए नहीं करना चाहते हैं) किसी भी कारण से उत्पादन नहीं की जरूरत है, तो आप इस छोटे संस्करण का उपयोग कर सकते कर बैकटिक के कम उपयोग और इसलिए कम भूमि के ऊपर:

OUTPUT=0; 
while [ "$OUTPUT" = 0 ]; do 
    OUTPUT=`$cmd | grep -c somestring`; 
done 

मार समारोह भी संस्करण:

function run_until() { 
    OUTPUT=0; 
    while [ "$OUTPUT" = 0 ]; do 
    OUTPUT=`$1 | grep -c $2`; 
    done 
} 
+0

आप उप-खोल में grep को पाइप करके खाली होने के लिए एक चर का परीक्षण करते हैं ??? आप गंभीर नहीं हो सकते! तथ्य यह है कि एक खोल आसानी से (कर सकते हैं हर खोल) और कहा कि जिस तरह से कोड बहुत ही जटिल है इस के लिए परीक्षण कर सकते हैं के बावजूद, यह भी अल्ट्रा inperformant है। – Mecki

+0

मुझे नहीं लगता कि वह खाली है, तो वह परीक्षण कर रहा है, वह यह निर्धारित करने के लिए grep का उपयोग कर रहा है कि चर में "somestring" है या नहीं।लेकिन वह पाइप किए गए grep को निम्न पंक्ति में ले जाकर आधे से उप-गोले की संख्या को कम कर सकता है जहां इसे OUTPUT को असाइन किया गया है, फिर WHILE एक खाली चर के लिए परीक्षण करेगा। –

+0

ऐसा लगता है कि यह पहली बार परीक्षण में विफल रहेगा क्योंकि OUTPUT के साथ शुरू करने के लिए खाली है? –

1
while (/bin/true); do 
    OUTPUT=`/some/command` 
    if [[ "x$OUTPUT" != "x" ]]; then 
    echo $OUTPUT 
    break 
    fi 

    sleep 1 
done 
+0

तो, x यहां खोज करने के लिए स्ट्रिंग है? अगर मैं foo खोज रहा था, तो मैं करता हूं: अगर [["foo $ OUTPUT"! = "Foo"]]; फिर ? –

+0

यदि "x $ OUTPUT" == "x" है, तो $ OUTPUT खाली है। यह सिर्फ जांचता है कि * कोई * आउटपुट है या नहीं। –

1

संपादित करें: मेरा मूल उत्तर यह मान रहा था कि "कुछ स्ट्रिंग" का अर्थ है "कोई स्ट्रिंग"। यदि आपको किसी विशिष्ट व्यक्ति की तलाश करने की आवश्यकता है, तो पर्ल शायद आपका सबसे अच्छा विकल्प है, क्योंकि REGEX मिलान की बात होने पर लगभग कुछ भी पर्ल को हरा नहीं सकता है।

हालांकि, यदि आप किसी भी कारण से पर्ल का उपयोग नहीं कर सकते हैं (आप पर्ल को अधिकांश लिनक्स डिस्ट्रोज़ में उपस्थित होने की उम्मीद कर सकते हैं, लेकिन कोई भी उपयोगकर्ता इसे इंस्टॉल करने के लिए मजबूर नहीं करता है, हालांकि पर्ल उपलब्ध नहीं हो सकता है), आप इसे कर सकते हैं grep की मदद से। हालांकि, मैंने अब तक देखे गए कुछ जीईपी समाधान उप-स्थानिक हैं (वे आवश्यक होने से धीमे हैं)। उस मामले में मैं नहीं बल्कि निम्नलिखित करना होगा:

MATCH=''; while [[ "e$MATCH" == "e" ]]; do MATCH=`COMMAND | grep "SOME_STRING"`; done; echo $MATCH 

साथ वास्तव में चलाने के लिए आदेश और स्ट्रिंग खोज करने के लिए साथ SOME_STRINGCOMMAND बदलें। यदि COMMAND के आउटपुट में SOME_STRING पाई जाती है, तो लूप रुक जाएगा और आउटपुट प्रिंट करेगा जहां SOME_STRING पाया गया था।

मूल जवाब:

नहीं

शायद सबसे अच्छा समाधान (मैं अच्छा नहीं बैश प्रोग्रामर हूँ), लेकिन यह काम :-P

RUN=''; while [[ "e$RUN" == "e" ]]; do RUN=`XXXX`; done ; echo $RUN 

बस अपने आदेश कॉल, उदा XXXX का स्थान ले लेगा का उपयोग करते हुए "गूंज" और इसे वापस कभी नहीं होगा (के रूप में गूंज stdout में प्रिंट कभी नहीं) की कोशिश, फिर भी अगर आप का उपयोग करें "गूंज परीक्षण" यह एक ही बार में समाप्त होगा और अंत में परीक्षण प्रिंट आउट।

+0

[["ई $ MATCH" == "ई"]] [[-n "$ MATCH"]] –

1
CONT=1; while [ $CONT -gt 0 ]; do $CMD | tee -a $FILE | grep -q $REGEXP; CONT=$? ; done 

टी आदेश एक पाइप में stdout पर कब्जा कर सकते हैं, जबकि अभी भी पर डेटा गुजर, और -a यह यह हर बार अधिलेखन के बजाय फ़ाइल को संलग्न करता है। grep -q अन्यथा अगर वहाँ एक मैच था return 0 जाएगा, 1 और stdout में लिखना नहीं है। $? पिछला आदेश की वापसी मूल्य है, इसलिए $CONT इस मामले में ग्रेप के रिटर्न मान हो जाएगा।

+0

बहुत आसान: $ सीएमडी तक टीई-ए $ फाइल | grep -q $ REGEXP; सो जाओ 1; किया गया ... जब तक grep की निकास स्थिति सफल नहीं हो जाती तब तक शेल पाइपलाइन को बार-बार निष्पादित करेगा। $ CONT या स्पष्ट संदर्भों के लिए $ कोई आवश्यकता नहीं है? –

+0

ओह, और मुझे यकीन नहीं है कि '-q' पोर्टेबल है; स्थिति 0 (मिला) या 1 (नहीं मिला) के साथ बाहर निकलने के लिए POSIX '-s' जरूरी है। –

0

यह करने के लिए एक आसान तरीका होगा

until `/some/command` 
do 
    sleep 1 
done 

आदेश के आसपास बैकटिक until परीक्षण बनाने के लिए कुछ उत्पादन आदेश के निकास मूल्य का परीक्षण करने के बजाय लौटा दी है।

+1

केवल बाहर निकलने की स्थिति का परीक्षण करता है, न कि stdout; इस प्रकार सवाल का जवाब नहीं है। –

+1

आपने आदेश के चारों ओर बैकटिक्स को याद किया जो मूल्यांकन तक मूल्यांकन करता है। मैं इसे स्पष्ट करने के लिए एक संपादन जोड़ दूंगा। –

+1

जब तक लूप रन/कुछ/कमांड चलाता है और आउटपुट स्थिति का परीक्षण करता है, तो इसका आउटपुट निष्पादित करता है। यह स्वाभाविक रूप से टूटा हुआ है। –

4

grep -c 99999 मैच के लिए संदर्भ से 99999 लाइनों प्रिंट होगा (मुझे लगता है यह पर्याप्त होगा):

while true; do /some/command | grep expected -C 99999 && break; done 

या

until /some/command | grep expected -C 9999; do echo -n .; done 

... इस प्रगति दर्शाते हुए कुछ अच्छा डॉट्स प्रिंट होगा ।

7

मैं हैरान मैं एक संक्षिप्त पर्ल एक लाइनर यहाँ उल्लेख नहीं देखा है हूँ:

perl -e 'do { sleep(1); $_ = `command`; print $_; } until (m/search/);' 

पर्ल इस तरह सामान के लिए वास्तव में एक अच्छा भाषा है। उस आदेश के साथ "कमांड" को बदलें जिसे आप बार-बार चलाना चाहते हैं। आप जिस खोज के लिए खोजना चाहते हैं उसके साथ "खोज" को बदलें। आप इसे में एक स्लैश के साथ कुछ के लिए खोज करने के लिए चाहते हैं, तो /es# साथ m#search तार के साथ m/search/ बदलें।

इसके अलावा, पर्ल Win32 सहित विभिन्न प्लेटफार्मों, के बहुत सारे पर चलता है, और जहां भी आप एक पर्ल स्थापना की है यह काम करेंगे। बस अपना आदेश उचित रूप से बदलें।

संबंधित मुद्दे

 संबंधित मुद्दे