프로그래밍 언어/Python

[Python] 파이썬 정규식 패턴변경자 g 설정 안되는 이유와 대체 기능

호무비 2024. 5. 5. 23:46
반응형

오늘은 파이썬에서 정규식 사용 시 패턴변경자 g 설정 적용하는 방법에 관해 알아보겠습니다. global 설정은 전체 문자열에 대해 패턴을 적용하는 패턴변경자입니다.

 

정규 표현식 상세 구현이 언어에 따라 다른 경우가 많은데, 이번에 파이썬에서 작업하면서 재미있는 차이점을 발견하여 소개해 보고자 합니다.


파이썬 정규식 패턴변경자 global 설정 문제

 

기존에 타입스크립트로 작성된 정규식 치환 로직이 있었는데, 잠깐 파이썬으로 옮겨야 하는 일이 생겨서 간단하게 코드를 작성해 보기로 하였습니다.

 

먼저 기존 코드부터 살펴보겠습니다. 문자열에서 공백 문자를 전부 줄바꿈 문자로 변경하는 간단한 코드입니다. 정규식은 \s와 패턴변경자 g 설정으로 간단하게 작성하였습니다.

 

const test = "adsada\tadad as adasdasda";

const result = test.replace(/\s/g, "\n");

console.log(result);

 

실행하면 다음과 같이 문자열이 줄바꿈으로 잘 바뀌어서 출력되는 것을 확인할 수 있습니다.

 

TypeScript 코드 실행 결과 (편의상 JavaScript로 작성함)

 

이번에는 해당 코드를 파이썬으로 작성해 보았습니다.

 

import re

test = "adsada\tadad as adasdasda"

result = re.sub(r"/\s/g", "\n", test)

print(result)

 

하지만 코드를 실행해 보니 문자열이 전혀 치환되지 않고 그대로였습니다.

 

Python 코드 실행 결과

 

파이썬은 /패턴/패턴변경자 형식이 아니라, 함수 인자로 지정해 준다는 사실을 알고 패턴변경자 설정을 살펴보았으나 global 플래그는 그 어디에도 없었습니다.

 

Python RegexFlag 관련 코드

 

stackoverflow를 찾아보니 파이썬은 해당 기능을 지원하지 않고 있었습니다.

 

https://stackoverflow.com/questions/11686516/python-regexp-global-flag

 

Python RegExp global flag

Is there a flag or some special key in python to use pattern multiple times. I used to test http://gskinner.com/RegExr/ my RegExp, it worked correctly in it. But when testing in correct enviorment ...

stackoverflow.com

 

반응형

대체 방안

 

그렇다면 같은 기능을 이용하려면 어떤 방법을 쓰면 될까요? 파이썬에서는 다른 함수를 통해 해당 기능을 지원하고 있는데, 한번 확인해 보도록 하겠습니다.

 

1. 치환 (replace)

문자열을 치환할 때는 앞서 사용했던 re.sub 함수를 사용하면 디폴트로 global 설정이 적용되어 전체 문자열을 치환합니다. 앞서 오류가 나던 코드에서 패턴구분자와 패턴변경자만 없애주면 아래와 같이 코드가 완성됩니다.

 

import re

test = "adsada\tadad as adasdasda"

result = re.sub(r"\s", "\n", test)

print(result)

 

실행 결과는 당연하게도 아주 잘 동작합니다.

 

Python 치환 코드 실행 결과

 

자바스크립트의 replace 함수는 패턴의 첫 번째 요소만 변경하는데, 파이썬도 같은 방식으로 동작할 것이라고 지레짐작하는 바람에 조금 더 고생을 한 것 같습니다.

 

실제 자바스크립트에서 패턴변경자를 없애면 아래와 같이 첫 번째 공백만 줄바꿈으로 변경해 주는 것을 확인하실 수 있습니다.

 

JavaScript 변형 코드 및 실행 결과

 

2. 검색 (search)

패턴에 해당하는 문자열을 모두 검색할 때는 findall 함수를 사용하면 됩니다. 앞선 코드에서 공백 문자열을 모두 찾는 코드로 한번 바꿔보겠습니다.

 

findall은 re.compile로 정규식 객체를 만들어야 사용할 수 있습니다. 해당 객체로 원하는 문자열을 검색하시면 됩니다.

 

import re

test = "adsada\tadad as adasdasda"

regex = re.compile(r"\s")
result = regex.findall(test)

print(result)

 

실행하면 아래와 같이 찾고자 했던 문자열을 모두 찾아서 배열 형태로 리턴해줍니다.

 

Python 검색 코드 실행 결과


번외편: 파이썬에서 첫 요소만 치환하고 싶다면?

 

파이썬은 re.sub 사용 시 디폴트로 global 설정이 적용된다고 설명해 드렸습니다. 그렇다면 첫 번째 요소만 replace하고 싶을 때에는 어떻게 하면 될까요?

 

방법은 간단합니다. re.sub 함수의 네 번째 인자로 count라는 값을 전달받는데, 이 값이 치환할 최대 문자 수를 의미합니다. 이 값을 1로 설정하면 자바스크립트에서 패턴변경자를 지정하지 않은 것과 같은 결과를 얻을 수 있습니다.

 

Python 변형 코드 및 실행 결과


파이썬에서 정규식 사용 시 g 패턴변경자 적용이 안 되는 문제에 관해 알아보았습니다. 정규식은 정해진 규칙이 있다 보니 언어마다 이렇게 차이가 날 줄 몰랐는데, 기본 정규식에서 확장된 기능을 지원하면서 구현이 달라지는 경우가 많이 있는 것 같습니다. 항상 사용하기 전에 유의해야 할 것 같습니다.

 

자세한 내용은 위키백과의 정규식 엔진 비교 문서를 읽어보시면 좋을 것 같습니다.

(링크: https://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines)

 

직접 조사해서 작성하는 글이다 보니 일부 정확하지 않은 정보가 포함되어 있을 수 있습니다.

궁금한 사항이나 잘못된 내용이 있으면 댓글로 알려주세요~

구독과 좋아요, 환영합니다!

 

반응형