दो मार्करों के बीच प्रतिस्थापन को कैसे निकालना है?


335

मान लीजिए कि मेरे पास एक स्ट्रिंग है 'gfgfdAAA1234ZZZuijjk'और मैं सिर्फ '1234'भाग निकालना चाहता हूं ।

मुझे केवल यह पता है कि कुछ अक्षर पहले क्या होंगे AAA, और ZZZभाग के बाद मुझे इसमें दिलचस्पी है 1234

इसके sedसाथ एक स्ट्रिंग के साथ ऐसा कुछ करना संभव है:

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"

और यह मुझे 1234परिणाम के रूप में देगा ।

पायथन में एक ही बात कैसे करें?

जवाबों:


587

नियमित अभिव्यक्ति का उपयोग करना - आगे के संदर्भ के लिए प्रलेखन

import re

text = 'gfgfdAAA1234ZZZuijjk'

m = re.search('AAA(.+?)ZZZ', text)
if m:
    found = m.group(1)

# found: 1234

या:

import re

text = 'gfgfdAAA1234ZZZuijjk'

try:
    found = re.search('AAA(.+?)ZZZ', text).group(1)
except AttributeError:
    # AAA, ZZZ not found in the original string
    found = '' # apply your error handling

# found: 1234

20
दूसरा समाधान बेहतर है, अगर पैटर्न ज्यादातर समय से मेल खाता है, क्योंकि इसकी आसान अनुमति से माफी के लिए पूछना है।
Bengt

7
क्या अनुक्रमण 0 पर शुरू नहीं होता है? तो आपको समूह (1) के बजाय समूह (0) का उपयोग करने की आवश्यकता होगी?
अलेक्जेंडर

22
@Alexander, नहीं, समूह (0) पूर्ण मिलान स्ट्रिंग लौटाएगा: AAA1234ZZZ, और समूह (1) केवल पहले समूह द्वारा मिलान किए गए वर्ण वापस करेगा: 1234
यूरी के के

1
@ बेंग्ट: ऐसा क्यों है? पहला समाधान मुझे काफी सरल लगता है, और इसमें कोड की कम लाइनें हैं।
नमस्तेगूडीबे जुले

5
इस अभिव्यक्ति में? गैर-लालची होने के लिए + को संशोधित करता है, अर्थात। यह किसी भी संख्या में 1 से ऊपर की तरफ से मेल खाएगा लेकिन जितना संभव हो उतना कम, केवल विस्तार करना। बिना?, पहला समूह 2ZZZkeAAA43 के रूप में gfgfAAA2ZZZkeAAA43ZZZonife से मेल खाएगा, लेकिन साथ? यह केवल 2 से मेल खाएगा, फिर कई के लिए खोज (या इसे छीन लिया और फिर से खोज करेगा) 43 से मेल खाएगा।
डोम

113
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'

फिर आप चाहें तो री मॉड्यूल के साथ रेगेक्स का भी उपयोग कर सकते हैं, लेकिन यह आपके मामले में आवश्यक नहीं है।


9
प्रश्न का तात्पर्य यह है कि इनपुट टेक्स्ट में हमेशा "AAA" और "ZZZ" दोनों शामिल होंगे। यदि यह मामला नहीं है, तो आपका उत्तर बुरी तरह से विफल हो जाता है (इसका मतलब है कि यह खाली स्ट्रिंग के बजाय कुछ पूरी तरह से गलत लौटाता है या अपवाद फेंक रहा है; "हेल्लो वहाँ" इनपुट स्ट्रिंग के रूप में सोचें)।
तीत

@ user225312 reविधि हालांकि तेज नहीं है?
भ्रमित

1
वोटअप, लेकिन मैं स्थिरता बनाए रखने के लिए "s.find ('AAA') + 3" के बजाय "x = 'AAA'? S.find (x) + len (x)" का उपयोग करूंगा।
एलेक्स

1
यदि टोकन में से कोई भी नहीं मिल सकता है s, s.findतो वापस आ जाएगा -1। स्लाइसिंग ऑपरेटर s[begin:end] इसे वैध सूचकांक के रूप में स्वीकार करेगा, और अवांछित प्रतिस्थापन लौटाएगा।
रिबमार


65

नियमित अभिव्यक्ति

import re

re.search(r"(?<=AAA).*?(?=ZZZ)", your_text).group(0)

AttributeErrorयदि कोई "AAA" और "ZZZ" में नहीं है तो उपरोक्त के रूप में विफल हो जाएगाyour_text

स्ट्रिंग विधियाँ

your_text.partition("AAA")[2].partition("ZZZ")[0]

यदि "AAA" या "ZZZ" मौजूद नहीं है तो उपरोक्त एक रिक्त स्ट्रिंग लौटाएगा your_text

पीएस अजगर चुनौती?


6
यह जवाब शायद अधिक वोटों का हकदार है। स्ट्रिंग विधि सबसे मजबूत तरीका है। इसे एक कोशिश / छोड़कर की आवश्यकता नहीं है।
चैमग

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

महान, बहुत धन्यवाद! - यह तार के लिए काम करता है और regex की आवश्यकता नहीं है
एलेक्स

15
import re
print re.search('AAA(.*?)ZZZ', 'gfgfdAAA1234ZZZuijjk').group(1)

1
AttributeError: 'NoneType' object has no attribute 'groups'- अगर कोई AAA, स्ट्रिंग में ZZZ नहीं है ...
eumiro

12

हैरानी की बात है कि किसी ने भी इसका उल्लेख नहीं किया है जो कि एकबारगी स्क्रिप्ट के लिए मेरा त्वरित संस्करण है:

>>> x = 'gfgfdAAA1234ZZZuijjk'
>>> x.split('AAA')[1].split('ZZZ')[0]
'1234'

@ user1810100 ने अनिवार्य रूप से उल्लेख किया है कि आपके द्वारा पोस्ट किए जाने से पहले लगभग 5 साल पहले का दिन ...
जॉन

10

आप कोड की सिर्फ एक पंक्ति का उपयोग कर सकते हैं

>>> import re

>>> re.findall(r'\d{1,5}','gfgfdAAA1234ZZZuijjk')

>>> ['1234']

परिणाम प्राप्त होगा सूची ...


7

आप उसके लिए पुनः मॉड्यूल का उपयोग कर सकते हैं :

>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)

5

Sed के साथ कुछ ऐसा करना संभव है जैसे कि एक स्ट्रिंग के साथ:

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"

और यह परिणाम के रूप में मुझे 1234 देगा।

आप एक re.subही regex का उपयोग करके फ़ंक्शन के साथ भी ऐसा कर सकते हैं ।

>>> re.sub(r'.*AAA(.*)ZZZ.*', r'\1', 'gfgfdAAA1234ZZZuijjk')
'1234'

बेसिक सेड में, कैप्चरिंग ग्रुप द्वारा प्रतिनिधित्व किया जाता है \(..\), लेकिन अजगर में इसका प्रतिनिधित्व किया गया था (..)


5

अजगर में, findallनियमित रूप से अभिव्यक्ति ( re) मॉड्यूल में विधि का उपयोग करके स्ट्रिंग स्ट्रिंग को निकाला जा सकता है ।

>>> import re
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> ss = re.findall('AAA(.+)ZZZ', s)
>>> print ss
['1234']

4

आप अपने कोड (वर्ण सूचकांक द्वारा) में इस फ़ंक्शन के साथ पहला सबस्ट्रिंग पा सकते हैं। इसके अलावा, आप एक विकल्प के बाद क्या पा सकते हैं।

def FindSubString(strText, strSubString, Offset=None):
    try:
        Start = strText.find(strSubString)
        if Start == -1:
            return -1 # Not Found
        else:
            if Offset == None:
                Result = strText[Start+len(strSubString):]
            elif Offset == 0:
                return Start
            else:
                AfterSubString = Start+len(strSubString)
                Result = strText[AfterSubString:AfterSubString + int(Offset)]
            return Result
    except:
        return -1

# Example:

Text = "Thanks for contributing an answer to Stack Overflow!"
subText = "to"

print("Start of first substring in a text:")
start = FindSubString(Text, subText, 0)
print(start); print("")

print("Exact substring in a text:")
print(Text[start:start+len(subText)]); print("")

print("What is after substring \"%s\"?" %(subText))
print(FindSubString(Text, subText))

# Your answer:

Text = "gfgfdAAA1234ZZZuijjk"
subText1 = "AAA"
subText2 = "ZZZ"

AfterText1 = FindSubString(Text, subText1, 0) + len(subText1)
BeforText2 = FindSubString(Text, subText2, 0) 

print("\nYour answer:\n%s" %(Text[AfterText1:BeforText2]))



2

बस किसी मामले में मुझे वही करना होगा जो मैंने किया था। मुझे कोष्ठक के अंदर सब कुछ एक पंक्ति में निकालना पड़ा। उदाहरण के लिए, यदि मेरे पास 'अमेरिकी राष्ट्रपति (बराक ओबामा) से मुलाकात जैसी कोई रेखा है ...' और मैं केवल 'बराक ओबामा' को प्राप्त करना चाहता हूं तो यह समाधान है

regex = '.*\((.*?)\).*'
matches = re.search(regex, line)
line = matches.group(1) + '\n'

यानी आपको slash \साइन के साथ कोष्ठक को अवरुद्ध करने की आवश्यकता है । हालांकि यह अधिक नियमित अभिव्यक्ति के बारे में एक समस्या है कि पायथन।

इसके अलावा, कुछ मामलों में आप रेगेक्स परिभाषा से पहले 'आर' प्रतीक देख सकते हैं। यदि कोई आर उपसर्ग नहीं है, तो आपको सी में भागने के पात्रों का उपयोग करने की आवश्यकता है। यहां पर उस पर अधिक चर्चा है।


2

PyParsing का उपयोग करना

import pyparsing as pp

word = pp.Word(pp.alphanums)

s = 'gfgfdAAA1234ZZZuijjk'
rule = pp.nestedExpr('AAA', 'ZZZ')
for match in rule.searchString(s):
    print(match)

कौन सी पैदावार:

[['1234']]


0

यहां रेगेक्स के बिना एक समाधान है जो उन परिदृश्यों के लिए भी जिम्मेदार है जहां पहले विकल्प में दूसरा विकल्प है। इस फ़ंक्शन को केवल एक विकल्प मिलेगा यदि दूसरा मार्कर पहले मार्कर के बाद है।

def find_substring(string, start, end):
    len_until_end_of_first_match = string.find(start) + len(start)
    after_start = string[len_until_end_of_first_match:]
    return string[string.find(start) + len(start):len_until_end_of_first_match + after_start.find(end)]

0

इसे करने का एक अन्य तरीका सूचियों का उपयोग करना है (आपके द्वारा ढूंढी जा रही सबस्टेशन को दबाकर संख्याओं से बना है, केवल):

string = 'gfgfdAAA1234ZZZuijjk'
numbersList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
output = []

for char in string:
    if char in numbersList: output.append(char)

print(f"output: {''.join(output)}")
### output: 1234

-1

एक लाइनर जो अन्य स्ट्रिंग को लौटाता है यदि कोई मैच नहीं था। संपादित करें: बेहतर संस्करण nextफ़ंक्शन का उपयोग करता है, "not-found"यदि आवश्यक हो तो कुछ और के साथ बदलें :

import re
res = next( (m.group(1) for m in [re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk" ),] if m), "not-found" )

यह करने के लिए मेरी दूसरी विधि, कम इष्टतम, रेगेक्स 2 बार का उपयोग करता है, फिर भी एक छोटा रास्ता नहीं मिला:

import re
res = ( ( re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk") or re.search("()","") ).group(1) )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.