पायथन एक्सट्रैक्ट पैटर्न मैच करता है


129

पायथन 2.7.1 मैं एक पैटर्न के अंदर शब्दों को निकालने के लिए अजगर नियमित अभिव्यक्ति का उपयोग करने की कोशिश कर रहा हूं

मेरे पास कुछ तार हैं जो इस तरह दिखते हैं

someline abc
someother line
name my_user_name is valid
some more lines

मैं "my_user_name" शब्द निकालना चाहता हूं। मैं कुछ ऐसा करता हूं

import re
s = #that big string
p = re.compile("name .* is valid", re.flags)
p.match(s) #this gives me <_sre.SRE_Match object at 0x026B6838>

अब मैं my_user_name कैसे निकालूं?

जवाबों:


159

आप regex से कब्जा करने की जरूरत है। searchपैटर्न के लिए, यदि पाया जाता है, तो स्ट्रिंग का उपयोग करके पुनः प्राप्त करें group(index)। मान्य चेक किए जाते हैं:

>>> p = re.compile("name (.*) is valid")
>>> result = p.search(s)
>>> result
<_sre.SRE_Match object at 0x10555e738>
>>> result.group(1)     # group(1) will return the 1st capture.
                        # group(0) will returned the entire matched text.
'my_user_name'

26
क्या आप वाकई group(0)पहले मैच के लिए नहीं हैं ?
शार्शॉस्की

33
देर से, लेकिन दोनों हाँ और नहीं। group(0)मिलान किए गए पाठ को लौटाता है, पहले कैप्चर समूह को नहीं। कोड टिप्पणी सही है, जबकि आप कैप्चर समूहों और मैचों को भ्रमित कर रहे हैं। group(1)पहला कब्जा समूह देता है।
andrewgu

1
मुझे मिलता हैNameError: name '_' is not defined
इयान जी

मुझे लगता है कि आपकी दूसरी पंक्ति पढ़नी चाहिए _ = p.search(s)। मैं देख रहा हूँ कि यह परिणाम निर्धारित करने का उल्लेख _करता है, लेकिन कोड यह प्रतिबिंबित नहीं करता है। मैं _ = p.search(s)उस दूसरी पंक्ति के लिए बदल गया और यह काम करता है।
इयान जी

2
@IanG मुझे क्षमा करें, मैं अपना उत्तर अपडेट करूंगा। BTW, एक मानक अजगर REPL के साथ, अंतिम परिणाम नामक एक विशेष चर में संग्रहीत किया जाता है _। यह बाहर कहीं और मान्य नहीं है।
अल्ट्रास्टिंक्ट

57

आप मिलान समूहों का उपयोग कर सकते हैं:

p = re.compile('name (.*) is valid')

जैसे

>>> import re
>>> p = re.compile('name (.*) is valid')
>>> s = """
... someline abc
... someother line
... name my_user_name is valid
... some more lines"""
>>> p.findall(s)
['my_user_name']

यहाँ मैं के re.findallबजाय re.searchसभी उदाहरण प्राप्त करने के लिए उपयोग करते हैं my_user_name। का उपयोग करते हुए re.search, आपको मैच ऑब्जेक्ट पर समूह से डेटा प्राप्त करने की आवश्यकता होगी:

>>> p.search(s)   #gives a match object or None if no match is found
<_sre.SRE_Match object at 0xf5c60>
>>> p.search(s).group() #entire string that matched
'name my_user_name is valid'
>>> p.search(s).group(1) #first group that match in the string that matched
'my_user_name'

जैसा कि टिप्पणियों में बताया गया है, आप अपने रेगेक्स को गैर-लालची बनाना चाहते हैं:

p = re.compile('name (.*?) is valid')

केवल 'name 'और अपने समूह में ' is valid'अन्य लेने के लिए अपने regex अनुमति देने के बजाय अगले और अगले सामान लेने के लिए ' is valid'


2
यह संभव है कि एक गैर-लालची मैच की आवश्यकता हो ... (जब तक कि एक उपयोगकर्ता नाम कई शब्द नहीं हो सकता ...)
जॉन क्लेमेंट्स

@ जॉन्सल्स - आपका मतलब है (.*?)? हाँ, यह संभव है, हालांकि यह आवश्यक नहीं है जब तक कि ओपी हमें प्रयोग न करेre.DOTALL
mgilson

हाँ - re.findall('name (.*) is valid', 'name jon clements is valid is valid is valid')शायद वांछित उत्पन्न नहीं करेगा परिणाम ...
जॉन क्लेमेंट्स

यह पायथन 2.7.1 के लिए काम नहीं करता है? यह सिर्फ एक पैटर्न ऑब्जेक्ट प्रिंट करता है?
कन्नन Ekanath

@ कैलेमस्टॉर्म - कौन सा हिस्सा काम नहीं करता है (मैंने python2.7.3 पर परीक्षण किया है)? जिस भाग का मैं उपयोग करता हूं .groupवह ठीक उसी तरह है जैसा आपने स्वीकार किया था ...
mgilson

16

आप कुछ इस तरह का उपयोग कर सकते हैं:

import re
s = #that big string
# the parenthesis create a group with what was matched
# and '\w' matches only alphanumeric charactes
p = re.compile("name +(\w+) +is valid", re.flags)
# use search(), so the match doesn't have to happen 
# at the beginning of "big string"
m = p.search(s)
# search() returns a Match object with information about what was matched
if m:
    name = m.group(1)
else:
    raise Exception('name not found')

10

शायद यह थोड़ा कम और समझने में आसान है:

import re
text = '... someline abc... someother line... name my_user_name is valid.. some more lines'
>>> re.search('name (.*) is valid', text).group(1)
'my_user_name'


9

आप स्ट्रिंग के हिस्सों को पकड़ने के लिए समूहों (संकेत के साथ '('और ')') का उपयोग कर सकते हैं । मैच ऑब्जेक्ट का group()तरीका तब आपको समूह की सामग्री देता है:

>>> import re
>>> s = 'name my_user_name is valid'
>>> match = re.search('name (.*) is valid', s)
>>> match.group(0)  # the entire match
'name my_user_name is valid'
>>> match.group(1)  # the first parenthesized subgroup
'my_user_name'

पायथन 3.6+ में आप उपयोग करने के बजाय एक मैच ऑब्जेक्ट में भी इंडेक्स कर सकते हैं group():

>>> match[0]  # the entire match 
'name my_user_name is valid'
>>> match[1]  # the first parenthesized subgroup
'my_user_name'

6

यहां समूहों (पायथन 3.6 या उससे ऊपर) का उपयोग किए बिना इसे करने का एक तरीका है:

>>> re.search('2\d\d\d[01]\d[0-3]\d', 'report_20191207.xml')[0]
'20191207'

1
यह पायथन रेगेक्स को संबोधित करता है, लेकिन ओपी के विशिष्ट प्रश्न को संबोधित नहीं करता है।
अलेस्टर तनेक जवास माज

इसके अलावा, यह मूल रूप से 3.6+ इंडेक्सिंग सिंटैक्स का उल्लेख करते हुए मौजूदा उत्तर में कुछ भी नया नहीं जोड़ता है।
यूजीन यर्मश

3

आप एक कैप्चर समूह का भी उपयोग कर सकते हैं (?P<user>pattern)और समूह को डिक्शनरी की तरह एक्सेस कर सकते हैं match['user']

string = '''someline abc\n
            someother line\n
            name my_user_name is valid\n
            some more lines\n'''

pattern = r'name (?P<user>.*) is valid'
matches = re.search(pattern, str(string), re.DOTALL)
print(matches['user'])

# my_user_name

1

ऐसा लगता है कि आप वास्तव में एक नाम निकालने की कोशिश कर रहे हैं, बस एक मैच खोजें। यदि यह स्थिति है, तो आपके मैच के लिए स्पान इंडेक्स होना सहायक है और मैं उपयोग करने की सलाह दूंगा re.finditer। एक शॉर्टकट के रूप में, आप जानते हैं कि nameआपके regex का हिस्सा लंबाई 5 और is validलंबाई 9 है, इसलिए आप नाम निकालने के लिए मिलान पाठ को स्लाइस कर सकते हैं।

नोट - आपके उदाहरण में, ऐसा लग रहा sहै कि लाइन ब्रेक के साथ स्ट्रिंग है, इसलिए यह नीचे मान लिया गया है।

## covert s to list of strings separated by line:
s2 = s.splitlines()

## find matches by line: 
for i, j in enumerate(s2):
    matches = re.finditer("name (.*) is valid", j)
    ## ignore lines without a match
    if matches:
        ## loop through match group elements
        for k in matches:
            ## get text
            match_txt = k.group(0)
            ## get line span
            match_span = k.span(0)
            ## extract username
            my_user_name = match_txt[5:-9]
            ## compare with original text
            print(f'Extracted Username: {my_user_name} - found on line {i}')
            print('Match Text:', match_txt)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.