정규식 일치하지만 파이썬에서 패턴의 일부만 바꿉니다.

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)

앞 / 뒤보기 패턴은 너비가 0이므로 아무것도 대체하지 않습니다.

UPD :

  • 문제는 re.sub앞과 뒤의 문자를 포함하여 일치하는 전체 표현식을 대체 한다는 것입니다.
  • re.findall여전히 전체 표현식과 일치하지만 그룹 (내부 괄호)도 포함되어 있습니다. 전체 경기는 여전히a_b
  • lookahead / lookbehind 표현식은 검색이 패턴의 앞 / 뒤에 있는지 확인하지만 일치 항목에 포함하지 않습니다.
  • 또 다른 옵션은 여러 그룹을 만들고 해당 그룹을 교체하는 것입니다. 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)