2014-10-14 5 views
5

एक bash स्क्रिप्ट में के लिए किसी और प्रिंट संदेश, मैं एक फ़ाइल मैं grep करना चाहते हैं में लाइनों की एक सूची है और फिर वहां से मानक है, जो थोड़ी देर के साथ किया सबसे आसान है पर प्रदर्शित पढ़ें:ग्रेप, कोई मेल नहीं

grep "regex" "filepath" | while read line; do 
    printf "$line\n" 
done 

हालांकि, मैं उपयोगकर्ता को सूचित करना चाहता हूं कि grep द्वारा कोई लाइन मेल नहीं खाती है। मुझे पता है कि कोई इसे updating a variable inside the loop द्वारा कर सकता है लेकिन ऐसा लगता है कि एक और अधिक सुरुचिपूर्ण दृष्टिकोण (यदि संभव हो) एक लूप तक एक रेखा को पढ़ने की कोशिश करना होगा, और यदि कोई आउटपुट नहीं था, तो एक त्रुटि संदेश प्रदर्शित किया जा सकता था।

यह मेरा पहला प्रयास था:

grep "regex" "filepath" | until [[ -z ${read line} ]]; do 
    if [[ -z $input ]]; then 
     printf "No matches found\n" 
     break 
    fi 
    printf "$line\n" 
done 

लेकिन इस उदाहरण में पढ़ें आदेश विकृत है, और मैं एक और तरीका वाक्यांश क्वेरी के बारे में सुनिश्चित नहीं था। क्या यह दृष्टिकोण संभव है, और यदि नहीं, तो समस्या का एक और अधिक उपयुक्त समाधान है?

+2

आपके पहले उदाहरण में, केवल grep की आवश्यकता है और आपको वही व्यवहार मिलता है। क्या यह सिर्फ एक उदाहरण के लिए है या आप वास्तव में क्या करना चाहते हैं? – jordanm

+0

क्या यह है? क्या आप दिखा सकते हैं कि कैसे? मैं अभी भी बैश के लिए काफी नया हूं और समझ नहीं पा रहा हूं कि उस व्यवहार को पाने के लिए grep का उपयोग कैसे करें। मैंने जो कोड लिखा है, वह अंतिम परिणाम दिखाता है जिसे मैं प्राप्त करने की कोशिश कर रहा हूं, अपने प्रश्न का उत्तर देने के लिए। आह बिल्ली अनावश्यक है। हटाया गया, धन्यवाद। – seraththundhuil

+0

grep मेल खाने वाली लाइनों को डिफ़ॉल्ट रूप से अपने मानक आउटपुट पर प्रिंट करता है, यही कारण है कि समय/पढ़ा हुआ लूप काम करता है यह मानक इनपुट पढ़ रहा है। बस 'grep "regex" "फ़ाइलपथ"' चलाएं और आपको अपनी मिलान रेखाएं देखना चाहिए। –

उत्तर

13

यदि आप कोई मिलान नहीं करते हैं तो आपको बस एक संदेश प्रदर्शित करना चाहते हैं तो आपको लूप की आवश्यकता नहीं है। इसके बजाय आप grep के रिटर्न कोड का उपयोग कर सकते हैं। एक साधारण if बयान पर्याप्त होगा:

if ! grep "regex" "filepath"; then 
    echo "no match" >&2 
fi 

यह ग्रेप मैचों में से परिणाम प्रदर्शित (के बाद से है कि ग्रेप का डिफ़ॉल्ट व्यवहार है) होगा, और अगर ऐसा नहीं होता है त्रुटि संदेश प्रदर्शित करेगा।

if ! का एक लोकप्रिय विकल्प || ऑपरेटर का उपयोग करना है। foo || bar को "foo या अन्य bar" के रूप में पढ़ा जा सकता है, या "foo नहीं तो bar"।

grep "regex" "filepath" || echo "no match" >&2 
1

जैसा कि @jordanm द्वारा उल्लिखित है, आपके द्वारा उल्लिखित उपयोग मामले में लूप की कोई आवश्यकता नहीं है।

output=$(grep "regex" "file") 
if [[ -n $output ]]; then 
    echo "$output" 
else 
    echo "Sorry, no results..." 
fi 

आप प्रसंस्करण (बजाय सिर्फ stdout में प्रदर्शित) के लिए परिणामों पर पुनरावृति करने की जरूरत है, तो आप कुछ इस तरह कर सकते हैं:

output=$(grep "regex" "file") 
if [[ -n $output ]]; then 
    while IFS= read -r line; do 
     # do something with $line 
    done <<< "$output" 
else 
    echo "Sorry, no results..." 
fi 

इस विधि एक पाइप लाइन या subshell ताकि का उपयोग कर से बचा जाता है लूप के भीतर किए गए किसी भी चरणीय असाइनमेंट को बाकी स्क्रिप्ट के लिए उपलब्ध होगा।

इसके अलावा, मुझे यकीन नहीं है कि यह आपके द्वारा किए जाने वाले प्रयासों से संबंधित है, लेकिन grep में फ़ाइल (प्रति पंक्ति एक) से पैटर्न लोड करने की क्षमता है। इसे निम्नानुसार कहा जाता है:

grep search_target -f pattern_file.txt 
1

जॉन कुगेलमैन का जवाब सही और संक्षिप्त है और आपको इसे स्वीकार करना चाहिए। मैं सिर्फ पूर्णता के लिए यहां वाक्यविन्यास के बारे में आपके प्रश्न को संबोधित कर रहा हूं।

निष्पादित करने के लिए आप ${read line} का उपयोग नहीं कर सकते हैं - ब्रेस सिंटैक्स वास्तव में इसका मतलब है (अस्पष्ट) कि आप एक वेरिएबल का मान चाहते हैं जिसका नाम एक स्थान है। शायद आप $(read line) के लिए शूटिंग कर रहे थे, लेकिन वास्तव में, उचित तरीके से अपने until पाश लिखने के

grep "regex" "filepath" | until read line; [[ -z "$line" ]]; do 

की तर्ज पर अधिक होगा ... लेकिन निश्चित रूप से, जब वहाँ कोई उत्पादन है, पाइप लाइन नहीं लाइनों प्राप्त होगा , इसलिए while और until दोनों यहां गलत हैं।

यह जोर देने योग्य है कि आपको अलग do की आवश्यकता है कि आप वहां कई आदेश प्राप्त कर सकते हैं। यहां तक ​​कि

while output=$(grep "regex filepath"); echo "grep done, please wait ..."; 
    count=$(echo "$output" | wc -l); [[ $count -gt 0 ]] 
do ... 

हालांकि फिर भी, यह वास्तव में आपको जितनी आवश्यकता होगी उससे कहीं अधिक आर्केन है। (और इस विशेष मामले में, तो आप शायद वास्तव में if, नहीं while चाहते चाहते हैं।)

दूसरों को पहले से ही बताया गया है, कि यहां ऐसे ही एक पाश का उपयोग करने का कोई कारण नहीं है, लेकिन मैं के बारे में कैसे सवाल को हल करना चाहता था जब भी आप वास्तव में एक चाहते हैं, इस तरह एक लूप लिखने के लिए।

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