Intro

파이썬 알고리즘 인터뷰 스터디 1회 후 정규 표현식에 대한 의문이 생겼다.

  1. re.sub(r’[^w+]’, ‘ ’, paragraph)
  2. re.sub(’[^w+]’, ‘ ’, paragraph)

정규 표현식 앞에 r prefix를 꼭 붙여야 하는 줄 알고 있었는데, 2번도 정상 작동을 했다. ..?

하나씩 뜯어보자

Regular Expression in Python

Regular expressions use the backslash character ('\') to indicate special forms or to allow special characters to be used without invoking their special meaning. This collides with Python’s usage of the same character for the same purpose in string literals.

정규식은 역 슬래시 문자('\')를 사용하여 특수 형식을 나타내거나 특별한 의미를 갖지 않고 특수 문자를 사용할 수 있게 합니다. 이것은 문자열에서 같은 목적을 위해 같은 문자를 사용하는 파이썬과 충돌합니다 .

The solution is to use Python’s raw string notation for regular expression patterns; backslashes are not handled in any special way in a string literal prefixed with 'r'. So r"\n" is a two-character string containing '\' and 'n', while "\n" is a one-character string containing a newline. Usually patterns will be expressed in Python code using this raw string notation.

해결책은 정규식 패턴에 파이썬의 raw string 표기법을 사용하는 것입니다;
역 슬래시는 'r' 접두어가 붙은 문자열 리터럴에서 특별한 방법으로 처리되지 않습니다. 따라서 r"\n"은 '\'와 'n'을 포함하는 두 글자 문자열이고, "\n"은 개행을 포함하는 한 글자 문자열입니다. 일반적으로 패턴은, 이 raw string 표기법을 사용하여 파이썬 코드로 표현됩니다.

출차: https://docs.python.org/3/library/re.html#

정리하자면 정규 표현식도 escape 문자와 마찬가지로 ‘\’ 를 이용하여 기존의 문자열이 아닌 특수 기능을 하는 문자로 사용한다. 중복되는 표현식(eg. \b)의 경우 충돌이 일어날 수 있다. 이 경우 일반적으로 escape string을 따른다. 이를 피하기 위해서 문자열 앞에 r prefix를 붙여 충돌을 피한다. r prefix에 대해서는 아래에 다시 얘기를 하겠다.

예제 코드

\b의 의미

  • escape string: back space

  • regex: word boundary

  • re.sub(”\b”, “A”, test_case)

    • 해당 코드에서는 \b가 escape string으로 작용되어 백스페이스의 의미를 갖는다. 따라서 test_case에서 백 스페이스를 찾아서 “A”로 바꾸는데 해당 케이스가 없어 문자열 그대로 출력되는 것을 확인할 수 있다.

백스페이스가 “A”로 대체된 예제

  • re.sub(r”\b”, “A”, test_case)
    • 해당 코드에서는 \b가 escape string이 아닌 정규표현식, word boundary의 의미를 갖는다. 단어들 주변에 “A”로 변경된 것을 확인할 수 있다.
  • re.sub(”\\b”, “A”, test_case)
    • \\b\\가 escape 되어 \로 변경되어 정규 표현식 \b으로 적용된 케이스이다. => r”\b” == “\\b”

r prefix 의미

Both string and bytes literals may optionally be prefixed with a letter 'r' or 'R'; such strings are called raw strings and treat backslashes as literal characters.

문자열 앞에 ‘r’ 접두사를 붙인 것을 raw string 이라하고 (백 슬래쉬)를 문자 취급한다.

출처 : https://docs.python.org/3/reference/lexical_analysis.html#literals

파이썬에서 문자열 앞에 “r” 접두사를 붙여서 raw string으로 선언을 하면 백 슬래쉬를 문자 취급한다. 즉, \t와 같이 escape 문자들을 무시하고 문자열로 치환할 수 있다.

위 예제를 보면 r prefix가 없는 경우에는 \t(탭)이 적용 된 것을 볼 수 있지만, r prefix가 적용된 경우 \가 문자 취급되어 탭이 적용되지 않고 “\t”로 출력된 것을 확인할 수 있다.

Result

여러가지 코드를 테스트 해보면서 정규 표현식와 escape string이 충돌되면 escape string을 따른다는 것을 확인할 수 있었다. 처음 의문을 가졌던 r’[^w+]'의 경우는 w+가 escape string에 해당하지 않아서 문제 없이 작동하였던 것이다.

하지만, escape string과 regular expression는 충돌할 가능성을 가지고 있고 \의 escape string으로써의 기능을 모두 계산하면서 (eg. \t ⇒ \t) 정규표현식을 쓰기에는 표현식이 너무 복잡해질 가능성이 있어 r prefix를 사용하는 것이 바람직해 보인다.

끝!

Reference

https://velog.io/@yoopark/r-prefix-in-regexp

https://docs.python.org/3/reference/lexical_analysis.html#literals

https://docs.python.org/3/library/re.html#

profile
반박 시 여러분의 말이 맞습니다.

0개의 댓글

Powered by GraphCDN, the GraphQL CDN