AWK: लाइन पैटर्न से एक्सेस कैप्चर ग्रुप


229

अगर मेरे पास एक awk कमांड है

pattern { ... }

और पैटर्न कैप्चरिंग समूह का उपयोग करता है, मैं ब्लॉक में कैप्चर किए गए स्ट्रिंग तक कैसे पहुंच सकता हूं?



कभी-कभी (साधारण मामलों में) फ़ील्ड सेपरेटर ( FS) को समायोजित करना संभव है और वह चुन सकता है जो एक के साथ मैच करना चाहेगा $field। इनपुट प्रीफॉर्मेट करने से भी मदद मिल सकती है।
Krzysztof Jabłoński

1
वहाँ एक है बेहतर जवाब डुप्लिकेट प्रश्न पर।
सैमुअल एडविन वार्ड

2
सैमुअल एडविन वार्ड: यह भी एक अच्छा जवाब है! लेकिन इसकी आवश्यकता भी है gawk(क्योंकि यह उपयोग करता है gensub)।
रैंपियन

जवाबों:


176

वह स्मृति लेन नीचे टहल रही थी ...

मैं एक लंबे समय से पहले perl द्वारा awk को बदल दिया।

जाहिरा तौर पर AWK नियमित अभिव्यक्ति इंजन अपने समूहों पर कब्जा नहीं करता है।

आप कुछ का उपयोग करने पर विचार कर सकते हैं जैसे:

perl -n -e'/test(\d+)/ && print $1'

-n ध्वज का कारण बनता है perl हर लाइन पर पाश की तरह awk करता है।


3
जाहिर तौर पर कोई असहमत है। यह वेब पेज 2005 से है: tek-tips.com/faqs.cfm?fid=5674 यह पुष्टि करता है कि आप aw में मेल खाने वाले समूहों का पुन: उपयोग नहीं कर सकते हैं।
पीटर टिलमन्स

3
मैं लगभग सभी उपयोग के मामलों के लिए 'perl -n -p -e ...' को अधिक पसंद करता हूं, क्योंकि यह अधिक लचीला, अधिक शक्तिशाली है और मेरी राय में एक सेर सिंटैक्स है।
पीटर टिलेमैन्स

15
gawk! = awk। वे अलग-अलग उपकरण हैं और gawkअधिकांश स्थानों पर डिफ़ॉल्ट रूप से उपलब्ध नहीं हैं।
ओली

6
ओपी ने विशेष रूप से एक अजीब समाधान के लिए कहा, इसलिए मुझे नहीं लगता कि यह एक उत्तर है।
Joppe

6
@ कोई समाधान नहीं होने पर आप एक अजीब समाधान नहीं दे सकते। पंक्ति 3 में मैं समझाता हूं कि AWK समूहों को पकड़ने का समर्थन नहीं करता है और मैंने एक विकल्प दिया, जिसे ओपी ने स्पष्ट रूप से सराहा क्योंकि इस उत्तर को स्वीकार कर लिया गया था। मैं इस प्रश्न का बेहतर उत्तर कैसे दे सकता था?
पीटर टिलेमैन्स

335

गौक के साथ, आप matchकोष्ठक समूहों को पकड़ने के लिए फ़ंक्शन का उपयोग कर सकते हैं ।

gawk 'match($0, pattern, ary) {print ary[1]}' 

उदाहरण:

echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}' 

आउटपुट cd

गौक के विशिष्ट उपयोग पर ध्यान दें जो प्रश्न में विशेषता को लागू करता है।

पोर्टेबल विकल्प के लिए आप के साथ match()और समान परिणाम प्राप्त कर सकते हैं substr

उदाहरण:

echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}'

आउटपुट cd


4
हां, gxxx वेरिएंट में बहुत सारी अतिरिक्त GNU अच्छाई और शक्ति है।
पीटर टिलमैंस

बिजीबॉक्स में भी काम करता है।
MrMas

32

यह एक ऐसी चीज है जिसकी मुझे हर समय आवश्यकता होती है इसलिए मैंने इसके लिए एक बश फ़ंक्शन बनाया। यह ग्लेन जैकमैन के जवाब पर आधारित है।

परिभाषा

इसे अपने .bash_profile आदि में जोड़ें।

function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }

प्रयोग

फ़ाइल में प्रत्येक पंक्ति के लिए regex कैप्चर करें

$ cat filename | regex '.*'

फ़ाइल में प्रत्येक पंक्ति के लिए 1 रेगेक्स कैप्चर समूह को कैप्चर करें

$ cat filename | regex '(.*)' 1

2
यह कैसे उपयोग करने से अलग है grep -o?
बफोंटेन

@bfontaine grep -oउत्पादन समूहों पर कब्जा कर सकता है ?
ओले हेर्स्टेडट

1
@ OlleHärstedt नहीं यह नहीं कर सका। जब आप कैप्चर-समूह नहीं रखते हैं तो यह केवल आपके उपयोग-मामले को कवर करता है। उस मामले में यह जंजीर के साथ बदसूरत हो जाता है grep -o
bfontaine

15

आप GNU awk का उपयोग कर सकते हैं:

$ cat hta
RewriteCond %{HTTP_HOST} !^www\.mysite\.net$
RewriteRule (.*) http://www.mysite.net/$1 [R=301,L]

$ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta
http://www.mysite.net/

12
+1। इसके अलावा, किसी भी जाग के साथ:awk 'match($0, /.*(http.*?)\$/) { print substr($0,RSTART,RLENGTH) }'
एड मॉर्टन

5
13

1
एड मॉर्टन: जो एक शीर्ष-स्तरीय उत्तर के हकदार हैं, मैं कहूंगा। संपादित करें: उम्म ... जो RewriteRule (.*) http://www.mysite.net/$मेरे लिए प्रिंट करता है, जो उपसमूह से अधिक है।
13


4

आप एक्सटेंशन के बिना भी वेनिला awk में कैप्चरिंग का अनुकरण कर सकते हैं। हालांकि यह सहज नहीं है:

चरण 1. कुछ स्ट्रिंग के साथ मैच को घेरने के लिए जेनबब का उपयोग करें जो आपके स्ट्रिंग में दिखाई नहीं देता है। चरण 2. चरित्र के खिलाफ विभाजन का उपयोग करें। स्टेप 3. स्प्लिट्ड ऐरे में हर दूसरा तत्व आपका कैप्चर ग्रुप है।

$ गूंज 'अब सीबी विज्ञापन' | awk '{विभाजन (gensub (/ a। /, SUBSEP "&" SUBSEP, "g", $ 0), टोपी, SUBSEP); प्रिंट कैप [2] "|" टोपी [4]; } '
अब | विज्ञापन

3
मैं लगभग निश्चित हूं कि gensubएक gawkविशिष्ट कार्य है। यदि आप टाइप करते हैं तो आपके जागरण से क्या मिलता है awk --version? -?)। सभी को सफलता मिले।
शेल्टर

6
मुझे पूरा यकीन है कि gensub एक gawk-ism है, हालांकि बिजीबॉक्स awk में भी है। यह उत्तर gsub का उपयोग करके भी लागू किया जा सकता है, हालांकि:echo 'ab cb ad' | awk '{gsub(/a./,SUBSEP"&"SUBSEP);split($0,cap,SUBSEP);print cap[2]"|"cap[4]}'
dubiousjim

3
gensub () एक gawk एक्सटेंशन है, gawk का मैनुअल स्पष्ट रूप से ऐसा कहता है। अन्य awk वैरिएंट भी इसे लागू कर सकते हैं, लेकिन यह अभी भी POSIX नहीं है। कोशिश करें gawk --posix '{gsub (...)}' और यह शिकायत करेगा
MestreLion

2
@MestreLion, आपका मतलब है कि यह शिकायत करेगा gawk --posix '{gensub(...)}'
डबियसजिम

1
बावजूद आप के बारे में गलत थे POSIX AWK होने gensubसमारोह, अपने उदाहरण एक बहुत ही सीमित परिदृश्य के लिए आवेदन किया: पूरे पैटर्न वर्गीकृत किया जाता है, यह सब कुछ इस तरह से मेल नहीं कर सकते हैं key=(value)जब मैं केवल निकालना चाहते हैं valueभागों।
मेव

2

मैं पीटर बैलेन्स के जवाब को लपेटता है जो एक बश फ़ंक्शन के साथ आने के लिए थोड़ा संघर्ष करता है, लेकिन यहाँ मैं क्या कर रहा हूं:

समारोह regex {perl -n -e "/ $ 1 / && printf \"% s \ n \ "," '$ 1'}

मैंने पाया कि यह नियमित अभिव्यक्ति तर्क के लिए ऑप्सब के awk- आधारित बेश फ़ंक्शन की तुलना में बेहतर काम करता है, क्योंकि मैं नहीं चाहता कि "ms" प्रिंट हो।

'([0-9]*)ms$'

मैं इस समाधान को पसंद करता हूं, क्योंकि आप समूह के कुछ हिस्सों को देख सकते हैं जो कैप्चर को सीमांकित करते हैं, जबकि उन्हें भी छोड़ देते हैं। हालांकि, क्या कोई इस बात पर ध्यान दे सकता है कि यह कैसे काम करता है? मुझे यह पर्ल सिंटैक्स BASH में ठीक से काम करने के लिए नहीं मिल सकता है, क्योंकि मैं इसे बहुत अच्छी तरह से नहीं समझता हूँ - विशेष रूप से डबल / सिंगल-क्वैस मार्क्स के आसपास$1
Demis

यह कुछ ऐसा नहीं है जो मैंने पहले या बाद में किया है, लेकिन यह देख रहा है कि यह क्या कर रहा है, दो तारों को समेट रहा है, पहला स्ट्रिंग डबल कोट्स में है (इस पहले स्ट्रिंग में एम्बेडेड डबल कोट्स बैकस्लैश के साथ भाग गए हैं) और दूसरा स्ट्रिंग सिंगल कोट्स में है । तब उस निष्कर्ष के परिणाम को तर्क-वितर्क के रूप में प्रदान किया जाता है। आपको यह भी जानना होगा कि पहले $ 1 (दोहरे कोट्स में से एक) को फ़ंक्शन के पहले तर्क के साथ प्रतिस्थापित किया गया है, जबकि दूसरा $ 1 (सिंगल कोट्स में एक) को अछूता छोड़ दिया गया है। देखें इस उदाहरण
wytten

मैं देख रहा हूं, यह अब थोड़ा अधिक समझ में आ रहा है। तो जहां पर्ल कमांड में रेगेक्स मैच / ग्रुप कैप्चर की परिभाषा है? मैं देख रहा हूं कि आपने लिखा है '([0-9]*)ms$'- कि एक तर्क के रूप में आपूर्ति की जाती है (और एक और तर्क)? और आउटपुट perl -eको बैश की printfकमांड में डाला जा रहा है , फिर बदलने के लिए %s, क्या यह सही है? धन्यवाद, मैं इसका उपयोग करने की उम्मीद कर रहा हूं।
डेमिस

1
आप एकल उद्धरणों में संलग्न एक नियमित अभिव्यक्ति को रेगेक्स बैश फ़ंक्शन के एकमात्र तर्क के रूप में पास करते हैं। उदाहरण
wytten
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.