रेगेक्स मैच के लिए, लेकिन केवल अजगर में पैटर्न के हिस्से को बदलें
स्टैक ओवरफ्लो पर मैंने जितने भी उदाहरण पाए हैं, वे मेरे लिए रिवर्स इंजीनियर के लिए बहुत जटिल हैं ।
इस खिलौना उदाहरण पर विचार करें
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)
#['_']
इसे प्रतिस्थापित क्यों नहीं किया जाता?
धन्यवाद
जवाब
लुक-फॉरवर्ड और लुक-बैक पैटर्न का उपयोग करें:
re.sub("(?<=[a-z])_(?=[a-z])","'",s)
आगे / पीछे पैटर्न देखें शून्य चौड़ाई है और इस प्रकार कुछ भी प्रतिस्थापित नहीं करते हैं।
युपीडी:
- समस्या यह थी कि
re.sub
पूर्व और निम्नलिखित पत्र सहित पूरे मिलान अभिव्यक्ति को बदल देगा। re.findall
अभी भी पूरी अभिव्यक्ति से मेल खा रहा था, लेकिन इसमें एक समूह (अंदर कोष्ठक) भी था, जिसे आपने देखा। पूरा मैच अभी बाकी थाa_b
- लुकहैड / लुकबाइंड एक्सप्रेशंस यह जाँचते हैं कि खोज एक पैटर्न से पहले / बाद में है, लेकिन इसे मैच में शामिल न करें।
- एक अन्य विकल्प कई समूहों को बनाना था, और उन समूहों को प्रतिस्थापन में लाना था:
re.sub("([a-z])_([a-z])", r"\1'\2", s)
उपयोग करते समय 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
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)