eşleştirmek için regex, ancak python'da kalıbın yalnızca bir kısmını değiştirin
Yığın taşmasıyla ilgili bulduğum tüm örnekler , tersine mühendislik yapamayacak kadar karmaşık .
Bu oyuncak örneğini düşünün
s = "asdfasd a_b dsfd"
İstiyorum s = "asdfasd a'b dsfd"
Yani: alt çizgiyle ayrılmış iki karakter bulun ve bu alt çizgiyi kesme işaretiyle değiştirin
Girişim:
re.sub("[a-z](_)[a-z]","'",s)
# "asdfasd ' dsfd"
()
Bu sorunu çözmesi gerektiğini sanıyordum.
Daha da kafa karıştırıcı, değiştirmek istediğimiz karakteri başarıyla bulduğumuz gerçeğidir:
re.findall("[a-z](_)[a-z]",s)
#['_']
bu neden değiştirilmiyor?
Teşekkürler
Yanıtlar
İleriye dönük ve arkaya bakma kalıplarını kullanın:
re.sub("(?<=[a-z])_(?=[a-z])","'",s)
İleriye / arkaya bak desenleri sıfır genişliğe sahiptir ve bu nedenle hiçbir şeyin yerini almaz.
UPD:
- Sorun,
re.sub
önceki ve sonraki harf dahil olmak üzere tüm eşleşen ifadenin yerini alacak olmasıdır. re.findall
hala tüm ifadeyle eşleşiyordu, ancak aynı zamanda gözlemlediğiniz bir grubu (içinde parantez) vardı. Bütün maç halaa_b
- Lookahead / lookbehind ifadeleri, aramanın önünde / arkasında bir kalıp olduğunu kontrol eder, ancak bunu eşleşmeye dahil etmez.
- başka bir seçenek de birkaç grup oluşturmak ve bu grupları yerine koymaktı:
re.sub("([a-z])_([a-z])", r"\1'\2", s)
Kullanılırken saklanacak re.sub
metin yakalanmalı, kaldırılacak metin alınmamalıdır.
Kullanım
re.sub(r"([a-z])_(?=[a-z])",r"\1'",s)
Kanıtı görün .
AÇIKLAMA
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
Python kodu :
import re
s = "asdfasd a_b dsfd"
print(re.sub(r"([a-z])_(?=[a-z])",r"\1'",s))
Çıktı:
asdfasd a'b dsfd
re.sub
O eşleşti her şeyi değiştirecektir.
Sorununuzu çözmenin daha genel bir yolu vardır ve normal ifadenizi yeniden değiştirmeniz gerekmez.
Aşağıdaki kod:
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)
çıktı: 'Data: year=am_replace_str, monthday=am_replace_str, month=am_replace_str, some other text'
Elbette, vakanız gruplar içermiyorsa, kodunuz şöyle olabilir:
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)