Awk का उपयोग करके मिलान रेगेक्स पैटर्न कैसे प्रिंट करें?


109

का उपयोग करते हुए awk, मुझे एक फ़ाइल में एक शब्द खोजने की आवश्यकता है जो एक रेगेक्स पैटर्न से मेल खाती है।

मैं केवल पैटर्न से मेल खाते शब्द को प्रिंट करना चाहता हूं ।

तो अगर लाइन में, मेरे पास है:

xxx yyy zzz

और पैटर्न:

/yyy/

मैं केवल प्राप्त करना चाहता हूं:

yyy

संपादित करें: kurumi के लिए धन्यवाद मैं इस तरह से कुछ लिखने में कामयाब रहा:

awk '{
        for(i=1; i<=NF; i++) {
                tmp=match($i, /[0-9]..?.?[^A-Za-z0-9]/)
                if(tmp) {
                        print $i
                }
        }
}' $1

और यह वही है जो मुझे चाहिए :) बहुत बहुत धन्यवाद!


1
@maxtaldykin क्या आप प्रश्न से अपना स्व-उत्तर अलग-अलग उत्तर में स्थानांतरित कर सकते हैं?
केनोरब

2
आपको करने की आवश्यकता नहीं है tmp=match($i, /regexp);if(tmp){}, आपको बस करने में सक्षम होना चाहिए if(tmp ~ $i){}क्योंकि ~इसका अर्थ है "रेगेक्सप से मेल खाता है"।
जस्टिनसीबी

जवाबों:


148

यह बहुत बुनियादी है

awk '/pattern/{ print $0 }' file

उपयोग awkकरने के लिए खोजने के लिए कहें , फिर लाइन का प्रिंट आउट लें, जिसे डिफ़ॉल्ट रूप से एक रिकॉर्ड कहा जाता है, जिसे $ 0 से चिह्नित किया जाता है। कम से कम प्रलेखन को पढ़ें ।pattern//

यदि आप केवल मिलान किए गए शब्द का प्रिंट आउट लेना चाहते हैं।

awk '{for(i=1;i<=NF;i++){ if($i=="yyy"){print $i} } }' file

49
चूंकि printडिफ़ॉल्ट कार्रवाई है: awk '/pattern/' fileपर्याप्त होगा।
जॉन्सवेब

18
@ जॉनोवेब, हां मैं इस तथ्य को जानता हूं। मारवर्क्स जैसी शुरुआत करने के लिए, इसका मतलब अधिक दृश्य होना था।
कुरुमी

21
मुझे आपके ज्ञान पर संदेह नहीं है। हालाँकि यह जानकारी दूसरों के लिए उपयोगी हो सकती है।
जॉन्सवेब

2
नायब: @marverix forको काम करने के लिए थोड़ा और होमवर्क करना होगा अगर (a) "yyy" एक रेगुलर एक्सप्रेशन है और स्ट्रेट स्ट्रिंग नहीं है और (b) अगर "yyy" एक पूरे फील्ड से मेल नहीं खाता है एक रिकॉर्ड।
जॉन्सवेब

8
यह नहीं होगा $i=="yyy"; यह $i ~ /yyy/एक नियमित अभिव्यक्ति के लिए होगा ।
जस्टिनसीबी

118

ऐसा लगता है कि आप GNU के grep -oव्यवहार का अनुकरण करने की कोशिश कर रहे हैं । यह ऐसा करेगा जो आपको केवल प्रत्येक पंक्ति पर पहला मैच प्रदान करना चाहता है:

awk 'match($0, /regex/) {
    print substr($0, RSTART, RLENGTH)
}
' file

यहाँ एक उदाहरण है, GNU के awkकार्यान्वयन का उपयोग करके ():

awk 'match($0, /a.t/) {
    print substr($0, RSTART, RLENGTH)
}
' /usr/share/dict/words | head
act
act
act
act
aft
ant
apt
art
art
art

के बारे matchमें substr, RSTARTऔर मैनुअल RLENGTHमें पढ़ें awk

उसके बाद आप एक ही लाइन पर कई मैचों से निपटने के लिए इसे विस्तारित करना चाह सकते हैं।


एनबी: उस अंतिम भाग का जवाब देने के लिए, सभी आवश्यक निर्माण कुर्मी के उत्तर और मेरे खुद के हैं।
जॉन्सवेब

बहुत बढ़िया जवाब। बस मैं यहाँ एक स्पष्टीकरण चाहूँगा क्योंकि मैं आलसी हूँ। लेकिन इसलिए मैं AWK का उपयोग कर रहा हूँ!
lukas.pukenis

क्या होगा अगर मैं प्रिंट के अलावा मैच परिणाम के साथ कुछ करना चाहता हूं? उदाहरण के लिए, मैं सभी मैचों को सरणी में जोड़ना चाहता हूं।
Evya2005

@ evya2005: आप बस कॉल रॉन प्रिंट को उस असाइनमेंट से बदल सकते हैं जिसकी आपको आवश्यकता है।
10:36

यह मेरे लिए काम नहीं कर रहा है। केवल प्रिंट कार्य। क्या आप मुझे उदाहरण दिखा सकते हैं?
Evya2005

36

gawk को हर लाइन के मिलते-जुलते भाग को क्रिया के रूप में प्राप्त कर सकते हैं:

{ if (match($0,/your regexp/,m)) print m[0] }

मैच (string, regexp [, array]) अगर array मौजूद है, तो यह क्लियर हो जाता है, और फिर array का zeroth एलिमेंट regexp द्वारा मैच किए गए स्ट्रिंग के पूरे हिस्से में सेट हो जाता है। यदि regexp में कोष्ठक शामिल हैं, तो सरणी के पूर्णांक-अनुक्रमित तत्व स्ट्रिंग के हिस्से को समतुल्य कोष्ठक उपसमिति से मिलान करने के लिए सेट होते हैं। http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions


13

यदि आप केवल इनपुट की अंतिम पंक्ति में रुचि रखते हैं और आप केवल एक मैच खोजने की उम्मीद करते हैं (उदाहरण के लिए शेल कमांड के सारांश लाइन का एक हिस्सा), तो आप इस बहुत कॉम्पैक्ट कोड को भी आज़मा सकते हैं, कैसे regexp मैचों को प्रिंट करने के लिए अपनाया गया `awk` का उपयोग कर? :

$ echo "xxx yyy zzz" | awk '{match($0,"yyy",a)}END{print a[0]}'
yyy

या आंशिक परिणाम के साथ अधिक जटिल संस्करण:

$ echo "xxx=a yyy=b zzz=c" | awk '{match($0,"yyy=([^ ]+)",a)}END{print a[1]}'
b

चेतावनी: awk match()तीन तर्कों वाला फ़ंक्शन केवल में मौजूद है gawk, अंदर नहींmawk

यहाँ एक और अच्छा समाधान के बजाय एक लुकअप regex का grepउपयोग कर रहा है awk। इस समाधान में आपके इंस्टॉलेशन की आवश्यकताएं कम हैं:

$ echo "xxx=a yyy=b zzz=c" | grep -Po '(?<=yyy=)[^ ]+'
b

आपने "पूंछ -n1" क्यों जोड़ा? यह इसके बिना ठीक काम करना चाहिए, नहीं?
आर्थर एकॉली जूल

1
@AththurAccioly सही। मैंने पिंग कॉल से औसत राउंडट्रिप समय निकालने के लिए इस शब्द का इस्तेमाल किया, यही वह जगह है जहां से यह आया था। अजीब बात है कि इसे खोजने में 4 साल लगे;)
डैनियल एल्डर

12

यदि पर्ल एक विकल्प है, तो आप यह कोशिश कर सकते हैं:

perl -lne 'print $1 if /(regex)/' file

केस-असंवेदनशील मिलान को लागू करने के लिए, iसंशोधक जोड़ें

perl -lne 'print $1 if /(regex)/i' file

मैच के बाद सब कुछ प्रिंट करने के लिए:

perl -lne 'if ($found){print} else{if (/regex(.*)/){print $1; $found++}}' textfile

मैच और मैच के बाद सब कुछ प्रिंट करने के लिए:

perl -lne 'if ($found){print} else{if (/(regex.*)/){print $1; $found++}}' textfile

3

इस स्थिति में सेड का प्रयोग भी सुरुचिपूर्ण हो सकता है। उदाहरण (लाइन से मिलान समूह "yyy" के साथ बदलें):

$ cat testfile
xxx yyy zzz
yyy xxx zzz
$ cat testfile | sed -r 's#^.*(yyy).*$#\1#g'
yyy
yyy

प्रासंगिक मैनुअल पेज: https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions


गैर-ग्नू सेड के लिए समाधान कुछ इस प्रकार है:sed -n 's/^.*\(yyy\).*$/\1/gp' < testfile
ग्रिगोरी एंटिन

1
@GrigoryEntin - bsd sed मूल उत्तर के साथ ठीक काम करता है। POSIX द्वारा समर्थित विस्तारित रेगेक्स स्विच -E है, लेकिन FreeBSD में कम से कम -r वही है, जैसे -E (-r 2010 में जोड़ा गया)। वैसे भी, ई के साथ प्रयास करें (gnu sed जोड़ा -E 4.3 में)
जुआन

3

ऑफ टॉपिक, यह grep का उपयोग करके भी किया जा सकता है, अगर कोई grep समाधान ढूंढ रहा है तो बस इसे यहां पोस्ट करना है

echo 'xxx yyy zzze ' | grep -oE 'yyy'

रेगेक्स के साथ भी इसे हथियाने का सरल तरीका। वास्तव में मुझे जो चाहिए था। धन्यवाद!
मार्की

यह मेरे लिए काम करता है; मेरा मामला इस तरह है: गूंज "web_port = 8080, shutdown_port = 8005" | grep -oE "web_port = [0-9] +" # 8080 लौटाएं
Robb Tsang

0

यदि आप जानते हैं कि जिस पाठ / पैटर्न को आप देख रहे हैं (उदाहरण के लिए "yyy") वह कौन सा कॉलम है, तो आप केवल उस विशिष्ट कॉलम को देख सकते हैं कि यह मेल खाता है या नहीं और इसे प्रिंट करें।

उदाहरण के लिए, निम्नलिखित सामग्रियों के साथ एक फ़ाइल दी गई है, ( asdf.txt )

xxx yyy zzz

केवल दूसरे कॉलम को प्रिंट करने के लिए यदि यह "yyy" पैटर्न से मेल खाता है, तो आप कुछ ऐसा कर सकते हैं:

awk '$2 ~ /yyy/ {print $2}' asdf.txt

ध्यान दें कि यह मूल रूप से किसी भी पंक्ति से मेल खाएगा जहां दूसरे कॉलम में "yyy" है, जैसे कि:

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