3P by neo 6달전 | favorite | 댓글 1개

Python 정규 표현식에서 "$" 문자의 동작에 대한 이해

  • Python의 re 모듈을 사용할 때, ^는 "문자열의 시작"을 의미하고, $는 "문자열의 끝"을 의미하는 것으로 알려져 있음.
  • 그러나 $는 항상 "문자열의 끝"만을 의미하지 않으며, 플랫폼에 따라 동작이 다를 수 있음.
  • Python에서는 멀티라인 모드가 비활성화되어 있을 때, $ 문자가 문자열의 끝 또는 문자열 끝의 개행 문자 전에 일치할 수 있음.

문자열 끝과 개행 문자 일치의 차이점

  • 멀티라인 모드가 비활성화된 상태에서 Python에서 개행 문자 없이 문자열의 끝에 일치시키려면 $만 사용해서는 안 됨.
  • 문자열의 끝에 일치시키기 위해 \z\Z를 사용할 수 있음.
  • Python에서 re.MULTILINE을 사용하면 $는 문자열의 끝과 각 줄의 끝(개행 문자 바로 앞)에 일치함.

다양한 플랫폼에서의 정규 표현식 동작 비교

  • 여러 플랫폼에서 "cat\n"에 대한 패턴 일치 여부를 비교한 표를 통해, 개행 문자를 포함하여 일치시키는 것이 허용된다면 멀티라인 모드에서 $를 사용하는 것이 일관되게 동작함.
  • 개행 문자를 포함하지 않고 일치시키려면, Python과 ECMAScript를 제외한 모든 플랫폼에서 \z를 사용하고, Python과 ECMAScript에서는 각각 \Z 또는 멀티라인 모드 없이 $를 사용해야 함.

GN⁺의 의견

  • 이 기사는 정규 표현식을 사용하는 개발자들에게 Python에서 $ 문자의 예상치 못한 동작에 대해 경각심을 줄 수 있음.
  • 정규 표현식은 문자열 처리에서 매우 강력하지만, 플랫폼마다 다른 동작을 보일 수 있어 주의가 필요함을 강조함.
  • 개발자들은 이러한 차이점을 인지하고, 크로스 플랫폼 애플리케이션을 개발할 때 호환성 문제를 피하기 위해 추가적인 테스트를 수행해야 할 필요가 있음.
  • 비슷한 기능을 제공하는 다른 정규 표현식 라이브러리로는 Java의 java.util.regex, .NET의 System.Text.RegularExpressions 등이 있으며, 이들도 각각의 플랫폼에 맞게 동작의 차이를 이해하고 사용해야 함.
  • 새로운 정규 표현식 문법이나 동작을 도입할 때는 기존 코드와의 호환성, 성능 영향, 그리고 팀 내에서의 학습 곡선을 고려해야 하며, 이러한 변경이 가져올 이점과 비용을 잘 평가해야 함.
Hacker News 의견
  • 정규 표현식에 익숙한 사람들은 ^가 "문자열의 시작"을 의미하고 $가 "문자열의 끝"을 의미한다는 것을 알 수 있음. 하지만 개인적으로는 이들을 "라인의 시작"과 "라인의 끝"으로 생각함. 대부분의 경우 텍스트를 한 줄씩 다루기 때문에 결과는 같지만, 이 연산자들을 생각할 때의 관점은 변하지 않음. 아마도 grep을 통해 정규 표현식을 처음 접하고 주로 "라인"으로 입력을 생각하기 때문일 것임.

    • POSIX 정규 표현식과 Python 정규 표현식은 다름. 일반적으로 사용하는 구현체의 정규 표현식 문서를 참조해야 하며, 문법은 보편적이지 않음.
    • POSIX 제9장에 따르면, 정규 표현식은 일반적으로 텍스트 처리와 관련이 있으며, 문자열의 끝을 나타내는 NUL로 끝나는 문자열에 대해 작동함. 일부 유틸리티는 처리를 줄 단위로 제한함. $는 문자열의 끝이나 줄의 끝에 해당할 수 있으며, 이는 유틸리티(또는 모드)에 따라 정의됨. 대부분의 일반적인 유틸리티(grep, sed, awk, Python 등)는 기본적으로 줄의 끝으로 처리함.
    • 단일 보편적인 정규 표현식 문법은 없음. 사용하는 언어와 옵션을 알지 못하면 정규 표현식을 신뢰할 수 있게 읽거나 쓸 수 없음.
  • Robert Elder를 소개하는 완벽한 기회임. 그는 YouTube와 블로그 콘텐츠를 만들며 정규 표현식에 대한 시리즈를 가지고 있고, 다양한 도구들의 행동 차이에 대해 깊이 파고듬.

  • 정규 표현식은 Perl을 처음 배울 때 진정으로 내면화한 첫 번째 것 중 하나임. (Perl은 여전히 "Camel" 책 덕분에 마음속에 따뜻한 자리를 차지하고 있음)

    • 오늘날 가장 중요한 정보는 구현체가 다르다는 것을 아는 것이며, 작업하는 것에 대한 참조 자료를 끌어오는 습관을 들임.
    • 예를 들어, Emacs 정규 표현식은 "\w" 대신 "\s_-" (또는 참조 자료 없이 화면에 무언가)를 문자 클래스로 사용하지만, Emacs는 최고의 문서화와 발견 가능성을 가지고 있음.
    • 일부 유틸리티는 괄호 이스케이핑을 요구하고 일부는 그렇지 않음. 때로는 이러한 동작이 구성 가능하고 때로는 그렇지 않음.
    • 혼란, 짜증, 부정의 단계를 모두 겪었으며 이제는 그저 받아들임. 개념은 어디에서나 동일하지만 풍미는 변함.
  • 나쁜 채용 관리자들이 '정규 표현식에서 문자열의 끝을 어떻게 매치하는가?'를 그들의 '하! 넌 속임수를 모르는구나!' 질문 목록에 추가하는 것을 들을 수 있음.

  • 정규 표현식과 관련하여 Perl을 목록에서 빼놓는 것은 이상함.

    • perlre 문서에서 $에 대한 설명: 문자열의 끝에 매치함 (또는 문자열 끝의 개행 문자 전에; 또는 /m을 사용할 경우 모든 개행 문자 전에)
  • Raku(이전의 Perl 6)는 문자열의 시작과 끝을 나타내기 위해 ^와 $를 선택하고, 줄의 시작과 끝을 나타내기 위해 ^^와 $$를 도입함. 다중 줄 모드는 사용 가능하지 않거나 필요하지 않음.

    • 완전한 재고/재작성의 이점 중 하나는, 이전 동작이 사람들을 놀라게 했다는 사실에서 배울 수 있다는 것임.
  • 정규 표현식이 표준화되었다고 생각하는 사람이 있음? 새로운 맥락으로 이동하는 것은 항상 다시 배우는 과정임.

  • 문자열과 줄에 대한 혼란이 있음. 문자열은 문자의 연속이고, 줄은 두 가지 다른 것일 수 있음. 개행 문자를 줄 종결자로 간주하면, 줄은 개행 문자를 포함한 비개행 문자의 연속임. 개행 문자가 없으면 완전한 줄이 아님. POSIX가 사용하는 것임. 개행 문자를 줄 구분자로 간주하면, 줄은 비개행 문자의 연속임. 어느 경우든 줄의 내용은 개행 문자 전에 끝남, 개행 문자가 줄을 종결시키기 때문이거나 다음 줄과 구분하기 때문임.

    • ^와 $의 의미는 줄에 기반을 둠 - 단일 줄 또는 다중 줄 모드 여부에 관계없이. 문자열 기반 의미 - 파일을 다룰 때 전체 파일로 생각할 수도 있음 - 에서는 \A와 \Z 또는 그에 상응하는 것을 사용함.
  • Ruby 기반 앱에서 몇 가지 심각한 버그로 이어짐. 항상 \A\z를 사용함.