source

regex 문자열 이스케이프

factcode 2022. 9. 20. 23:52
반응형

regex 문자열 이스케이프

일부 텍스트를 검색할 때 사용자의 입력을 정규식 패턴으로 사용하고 싶습니다.동작합니다만, 유저가 regex 에 의미를 가지는 문자를 넣는 경우는 어떻게 대응합니까?

를 들어,는 단어 .(s)은 regex 를 합니다.(s)처럼 좋겠다"(s)" 는 달릴 수 replace에 따라 ""를 .(\()\)하지만 문제는 가능한 모든 regex 기호를 교체해야 한다는 것입니다.

더 좋은 방법을 알고 있니?

하다를 사용하세요.re.escape()★★★★

4.2.3re 내용

이스케이프(스트링)

영숫자가 아닌 모든 백슬래시를 포함한 문자열을 반환합니다.정규 표현 메타 문자를 포함할 수 있는 임의의 리터럴 문자열과 일치시킬 때 유용합니다.

간단한 예에서는 옵션에서 s 뒤에 오는 문자열이 있으면 검색하여 일치 개체를 반환합니다.

def simplistic_plural(word, text):
    word_or_plural = re.escape(word) + 's?'
    return re.match(word_or_plural, text)

다음을 사용할 수 있습니다.

re.escape(string) 영숫자가 아닌 모든 백슬래시를 포함한 문자열을 반환합니다.이것은 정규 표현 메타 문자를 포함할 가능성이 있는 임의의 리터럴 문자열과 일치시키는 경우에 편리합니다.

>>> import re
>>> re.escape('^a.*$')
'\\^a\\.\\*\\$'

Python 버전 < 3.7 을 사용하고 있는 경우는, 정규 표현 구문의 일부가 아닌 영숫자가 아닌 것도 이스케이프 됩니다.

Python 버전 < 3.7 > = 3.3 을 사용하고 있는 경우, 이것은 정규 표현 구문의 일부가 아닌, 특별히 밑줄( )을 제외하고, 비언어적인 것을 회피합니다._를 참조해 주세요.

유감스럽게도 는 치환 문자열에 적합하지 않습니다.

>>> re.sub('a', re.escape('_'), 'aa')
'\\_\\_'

해결책은 대체품을 람다에 넣는 것입니다.

>>> re.sub('a', lambda _: '_', 'aa')
'__'

람다의 반환값이 리터럴 문자열로 처리되기 때문입니다.

오웬의 대답은 모순으로 이어질 수 있다.람다는 함수 호출의 인라인 치환일 뿐이지만 다음과 같이 다른 결과를 생성합니다.예를 들어 복잡도를 높이기 위해 람다를 함수 호출로 '업그레이드'해야 하는 경우, 이는 갑자기 중단됩니다.

import re

xml = """pre@mytag@123@/mytag@post"""

replacewith = '@mytag@456 \\1@/mytag@'

regexp = re.compile(r'@mytag@(.*?)@/mytag@', re.S|re.M|re.I)

def rw(inp):

  return inp

result = regexp.sub(lambda _: replacewith, xml)

print(result) # desired result

result = regexp.sub(rw(replacewith), xml)

print(result) # undesired result

보통 정규식에 입력하는 문자열을 이스케이프하면 정규식은 문자 그대로 해당 문자를 간주합니다.보통 컴퓨터에 문자열을 입력하면 컴퓨터가 특정 문자를 삽입합니다. ★★★★★★★★★★★★★★★★★★★★★★★★.\n파서가 결정하기 전까지는 새로운 행이 아닙니다.두 글자예요.비단뱀을 통과하면print는 그것을 표시해, 새로운 행으로서 해석합니다만, 에디터에 표시되는 텍스트에서는, 백슬래시의 문자 뒤에 n이 붙을 가능성이 있습니다.네가 한다면.\r"\n"그러면 python은 항상 사용자가 입력한 raw로 해석합니다(제가 이해하기로는).문제를 더욱 복잡하게 만드는 것은 정규식에 또 다른 구문/문법이 있다는 것입니다.regex 파서는 수신된 문자열을 python의 print와 다르게 해석합니다.그렇기 때문에 이런 생현악기 같은 걸 건네는 게 좋을 것 같아요.r"(\n+)--그러면 regex는 실제로 입력한 내용을 수신합니다.그러나 regex 자체 구문 규칙을 사용하도록 명시적으로 지시하지 않는 한 regex는 괄호를 수신하고 리터럴 괄호로 일치하지 않습니다.그러기 위해서는r"(\fun \( x : nat \) :)"여기서는 첫 번째 패런은 백슬래시가 없기 때문에 캡처 그룹이기 때문에 매칭되지 않지만 두 번째 패런은 리터럴 패런으로 매칭됩니다.

우리는 보통 이렇게 한다.re.escape(regex)문자 그대로 해석하고 싶은 것을 회피하기 위해, 예를 들어 regex 파라세서에 의해 일반적으로 무시되는 것(예: parens, space 등)이 회피됩니다.예를 들어, 앱에 있는 코드:

    # escapes non-alphanumeric to help match arbitrary literal string, I think the reason this is here is to help differentiate the things escaped from the regex we are inserting in the next line and the literal things we wanted escaped.
    __ppt = re.escape(_ppt)  # used for e.g. parenthesis ( are not interpreted as was to group this but literally

예: 다음 문자열을 참조하십시오.

_ppt
Out[4]: '(let H : forall x : bool, negb (negb x) = x := fun x : bool =>HEREinHERE)'
__ppt
Out[5]: '\\(let\\ H\\ :\\ forall\\ x\\ :\\ bool,\\ negb\\ \\(negb\\ x\\)\\ =\\ x\\ :=\\ fun\\ x\\ :\\ bool\\ =>HEREinHERE\\)'
print(rf'{_ppt=}')
_ppt='(let H : forall x : bool, negb (negb x) = x := fun x : bool =>HEREinHERE)'
print(rf'{__ppt=}')
__ppt='\\(let\\ H\\ :\\ forall\\ x\\ :\\ bool,\\ negb\\ \\(negb\\ x\\)\\ =\\ x\\ :=\\ fun\\ x\\ :\\ bool\\ =>HEREinHERE\\)'

이중 백슬래시는 regex가 문자 그대로 백슬래시를 수신하도록 되어 있습니다.


그런데 단일 백슬래시가 아닌 이중 백슬래시를 출력한 것이 놀랍습니다.그것에 대해 코멘트해 주시면 감사하겠습니다.또한 현재 regex에 있는 문자 그대로의 백슬래시를 어떻게 일치시키는지도 궁금합니다.4개의 백슬래시라고 생각합니다만, raw string r constructure로 인해 2개만 필요할 것이라고 솔직히 예상했습니다.

시험해 보세요.

\Q 및 \E를 앵커로 합니다.

전체 단어 또는 정규식과 일치하도록 Or 조건을 지정합니다.

참조 링크 : regex에 특수문자가 포함된 단어 전체를 대조하는 방법

언급URL : https://stackoverflow.com/questions/280435/escaping-regex-string

반응형