Awk / pattern / {print "text"} / patern / {print ""} का उपयोग करते समय क्या कोई ELSE पैटर्न है?


22

मान लीजिए कि मेरे पास टेक्स्ट फाइल है जैसे:

R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

मैं awkइन लाइनों को अलग तरह से संसाधित करने के लिए उपयोग करना चाहता हूं , जैसे

awk '/R1/ { print "=>" $0} /R2/ { print "*" $0} '

और मैं बाकी सभी पंक्तियों को भी प्रिंट करना चाहता हूं क्योंकि वे हैं (उन लाइनों के डुप्लिकेट बनाने के बिना जो मैंने पहले ही संसाधित किए हैं), मूल रूप से मुझे /ELSE/ { print $0}अपनी awkरेखा के अंत में आवश्यकता है ।

क्या वहां ऐसी कोई चीज है?

जवाबों:


27

के साथ सरलीकृत दृष्टिकोण awk

awk '/R1/ {print "=>" $0;next} /R2/{print "*" $0;next} 1' text.file

[jaypal:~/Temp] cat text.file 
R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

[jaypal:~/Temp] awk '/R1/ { print "=>" $0;next} /R2/{print "*" $0;next}1' text.file
=>R1 12 324 3453 36 457 4 7 8
*R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
[jaypal:~/Temp] 

ब्रेकआउट ऑफ़ पैटर्न {एक्शन} विवरण:

  • /R1/ { print "=>" $0;next}: इसका मतलब है कि /R1/छपाई की क्रिया करने वाली लाइनें =>होगी। nextइसका मतलब यह है कि बाकी अटपटे बयानों को नजरअंदाज कर दिया जाएगा और अगली पंक्ति को देखा जाएगा।

  • /R2/{print "*" $0;next}: इसका मतलब है कि pattern /R2/छपाई की कार्रवाई से मेल खाने वाली लाइनें *होगी। जब awkप्रसंस्करण शुरू होता है, तो पहले pattern {action}बयान को नजरअंदाज कर दिया pattern /R1/जाएगा क्योंकि होने वाली लाइनों के लिए इच्छा सही नहीं होगी /R2/। तो दूसरा pattern {action}बयान लाइन पर किया जाएगा। nextफिर से मतलब होगा कि हम कोई और प्रसंस्करण नहीं चाहते हैं और awkअगली पंक्ति में विधिवत जाएंगे।

  • 1सभी लाइनों को प्रिंट करता है। जब कोई शर्त नहीं के साथ आपूर्ति की जाती है {action}, तो उपयोग करने के लिए डिफॉल्ट जागृत करें {print}। यहाँ वह स्थिति है 1जिसकी व्याख्या सही है, इसलिए यह हमेशा सफल होती है। यदि हम इस बिंदु पर पहुँचते हैं, तो ऐसा इसलिए है क्योंकि पहले और दूसरे pattern {action}विवरणों को अनदेखा किया गया था या पास-पास (युक्त लाइनों के लिए /R1/और नहीं /R2/), इसलिए शेष लाइनों के लिए डिफ़ॉल्ट प्रिंट कार्रवाई की जाएगी।


लगता है कि पोस्ट किए गए सभी समाधानों में से सबसे तेज़ी से चला जाए।
क्रिस डाउन

1
मुझे यकीन नहीं है कि सिंटैक्टिक शुगर यहाँ सही शब्द है ... यह सिंटेक्स है।
डैनियल हर्शकोविच

7

awkसशर्त होने पर सामान्य संदिग्धों को लागू करता है। यह उस नौकरी printfके printलिए उपयोग करने के लिए एक अच्छा विचार है जो आप मैच पर करना चाहते हैं।

awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'

इसके लिए आपको वास्तव में जरूरत नहीं है if-then-else
जयपाल सिंह

1
जबकि यह पूरी तरह से अच्छी तरह से काम करता है, यह मुहावरेदार नहीं है। nextAwk programing में विवेकपूर्ण उपयोग एक महत्वपूर्ण उपकरण है।
dmckee

2
मैं printfयहाँ प्रयोग करने की बात नहीं समझता । इसका एकमात्र फायदा (जब तक आप कंसेंट की तुलना में कट्टरपंथी प्रारूपण नहीं कर रहे हैं) यह है कि यह एक नई पंक्ति नहीं जोड़ता है, जो यहां प्रासंगिक नहीं है।
गाइल्स का SO- बुराई पर रोक '

1
यह एक नकली और आश्चर्यजनक परिणाम है। printकेवल असंबद्ध को आउटपुट करना पड़ता है $0जबकि printfएक प्रारूप स्ट्रिंग को पार्स करना पड़ता है।
jw013

5

क्रिस डाउन ने पहले ही दिखाया कि आप किसी ब्लॉक में 'स्पष्ट' कथन का उपयोग करके रीजैक्स के लिए और कैसे प्राप्त कर सकते हैं। आप कुछ अन्य तरीकों से भी समान प्रभाव प्राप्त कर सकते हैं, हालांकि उसका समाधान संभवतः बेहतर है।

एक तीसरा रेगेक्स लिखना है जो केवल पाठ से मेल खाएगा दूसरों से मेल नहीं खाता है, आपके मामले में, यह कुछ इस तरह दिखाई देगा:

awk '/^R1/ { print "=>" $0}
     /^R2/ { print "*" $0}
     /^[^R]/ || /^R[^12]/ { print $0 } '

ध्यान दें, यह एंकरेड रेग्जैप्स का उपयोग करता है - ^ रेगेक्स की शुरुआत में ^ केवल एक लाइन की शुरुआत में मेल खाएगा - आपके मूल पैटर्न ने ऐसा नहीं किया, जो मिलान को थोड़ा धीमा कर देता है क्योंकि यह एक लाइन पर सभी वर्णों की जांच करेगा। अगली पंक्ति तक लंघन। तीसरा ("और") मामला एक ऐसी रेखा से मेल खाता है जो किसी ऐसे वर्ण से शुरू होता है जो 'R' ([^ R]) नहीं है या जो कि 'R' से शुरू होता है और उसके बाद एक वर्ण '1' या ' 2 '(आर [^ 12])। ^ के दो अलग-अलग अर्थ कुछ भ्रमित करने वाले हैं, लेकिन यह गलती बहुत समय पहले की गई थी और जल्द ही इसे कभी भी नहीं बदला जाएगा।

पूरक रेग्जाप्स का उपयोग करने के लिए, उन्हें वास्तव में एंकरिंग करने की आवश्यकता होती है, अन्यथा अन्यथा [^ R] 1 के बाद से मेल खाएगा। आपके जैसे बहुत ही सरल रीजैक्स के लिए, यह दृष्टिकोण उपयोगी हो सकता है, लेकिन जैसे-जैसे रेक्सएक्सप्स अधिक जटिल होते जाते हैं, यह दृष्टिकोण असहनीय हो जाएगा। इसके बजाय, आप प्रत्येक पंक्ति के लिए राज्य चर का उपयोग कर सकते हैं, जैसे:

awk '{ handled = 0 }
     /^R1/ { print "=>" $0; handled = 1}
     /^R2/ { print "*" $0; handled = 1}
     { if (!handled) print $0 } '

यह सेट प्रत्येक नई पंक्ति के लिए शून्य पर संभाला जाता है, फिर 1 पर अगर यह दोनों रीगेक्स में से किसी एक से मेल खाता है, और अंत में, यदि यह अभी भी शून्य है, तो प्रिंट $ 0 को निष्पादित करता है।


यह ध्यान दिया जाना चाहिए कि बड़ी फ़ाइलों पर दोनों सशर्त का उपयोग करने की तुलना में कम कुशल हैं (जैसा कि यहां दिखाया गया है )। rfileप्रश्नकर्ता के डेटासेट की सिर्फ 10000 पंक्तियों को दोहराया जाता है।
क्रिस डाउन

4
if (!handled)नीरस nextअन्य कार्यों पर विचार करने से रोकने के लिए उपयोग करें ।
dmckee

के लिए +1 if (!handled)। सामान्य, लचीले, पुन: प्रयोज्य समाधान अच्छे हैं। क्या होगा अगर इस सवाल का अगला व्यक्ति मुद्रण के बाद अधिक प्रसंस्करण करना चाहता है? जिन उत्तरों का nextसमर्थन नहीं करता है।
स्कॉट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.