रेगेक्स मैच के लिए, लेकिन केवल अजगर में पैटर्न के हिस्से को बदलें

Aug 17 2020

स्टैक ओवरफ्लो पर मैंने जितने भी उदाहरण पाए हैं, वे मेरे लिए रिवर्स इंजीनियर के लिए बहुत जटिल हैं

इस खिलौना उदाहरण पर विचार करें

s = "asdfasd a_b dsfd"

मुझे चाहिए s = "asdfasd a'b dsfd"

वह यह है: दो अक्षरों को एक अंडरस्कोर द्वारा अलग करें और एक एपोस्ट्रोफी के साथ उस अंडरस्कोर को बदलें

प्रयास करें:

re.sub("[a-z](_)[a-z]","'",s)
# "asdfasd ' dsfd"

मैंने सोचा था कि ()इस समस्या को हल करने वाले थे?

इससे भी अधिक भ्रामक तथ्य यह है कि ऐसा लगता है कि हम उस चरित्र को सफलतापूर्वक पा चुके हैं जिसे हम बदलना चाहते हैं:

re.findall("[a-z](_)[a-z]",s)
#['_']

इसे प्रतिस्थापित क्यों नहीं किया जाता?

धन्यवाद

जवाब

3 Marat Aug 17 2020 at 00:27

लुक-फॉरवर्ड और लुक-बैक पैटर्न का उपयोग करें:

re.sub("(?<=[a-z])_(?=[a-z])","'",s)

आगे / पीछे पैटर्न देखें शून्य चौड़ाई है और इस प्रकार कुछ भी प्रतिस्थापित नहीं करते हैं।

युपीडी:

  • समस्या यह थी कि re.subपूर्व और निम्नलिखित पत्र सहित पूरे मिलान अभिव्यक्ति को बदल देगा।
  • re.findallअभी भी पूरी अभिव्यक्ति से मेल खा रहा था, लेकिन इसमें एक समूह (अंदर कोष्ठक) भी था, जिसे आपने देखा। पूरा मैच अभी बाकी थाa_b
  • लुकहैड / लुकबाइंड एक्सप्रेशंस यह जाँचते हैं कि खोज एक पैटर्न से पहले / बाद में है, लेकिन इसे मैच में शामिल न करें।
  • एक अन्य विकल्प कई समूहों को बनाना था, और उन समूहों को प्रतिस्थापन में लाना था: re.sub("([a-z])_([a-z])", r"\1'\2", s)
2 RyszardCzech Aug 17 2020 at 02:48

उपयोग करते समय re.sub, रखने के लिए पाठ कैप्चर किया जाना चाहिए, हटाने के लिए पाठ नहीं होना चाहिए।

उपयोग

re.sub(r"([a-z])_(?=[a-z])",r"\1'",s)

प्रमाण देखें ।

व्याख्या

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    [a-z]                    any character of: 'a' to 'z'
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  _                        '_'
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    [a-z]                    any character of: 'a' to 'z'
--------------------------------------------------------------------------------
  )                        end of look-ahead

पायथन कोड :

import re
s = "asdfasd a_b dsfd"
print(re.sub(r"([a-z])_(?=[a-z])",r"\1'",s))

आउटपुट:

asdfasd a'b dsfd
ShinNShirley Sep 30 2020 at 14:33

re.subसब कुछ यह मिलान किया बदल देगा।

आपकी समस्या को हल करने का एक और सामान्य तरीका है, और आपको अपनी नियमित अभिव्यक्ति को फिर से संशोधित करने की आवश्यकता नहीं है।

नीचे कोड:

import re


s = 'Data: year=2018, monthday=1, month=5, some other text'
reg = r"year=(\d{4}), monthday=(\d{1}), month=(\d{1})"


r = "am_replace_str"
def repl(match):
    _reg = "|".join(match.groups())
    return re.sub(_reg, r,match.group(0)) if _reg else r

# 
re.sub(reg,repl, s)

उत्पादन: 'Data: year=am_replace_str, monthday=am_replace_str, month=am_replace_str, some other text'

बेशक, अगर आपके मामले में समूह नहीं हैं, तो आपका कोड इस तरह हो सकता है:

import re


s = 'Data: year=2018, monthday=1, month=5, some other text'
reg = r"year=(\d{4}), monthday=(\d{1}), month=(\d{1})"


r = "am_replace_str"
def repl(match):
    _reg = "|".join(match.groups())
    return re.sub(_reg, r,match.group(0))

# 
re.sub(reg,repl, s)