본문 바로가기

연구노트/Python

Python 정규 표현식

 

 

Python 정규 표현식

 

정규 표현식 살펴보기

 

정규 표현식은 복잡한 문자열을 처리할 때 사용하는 기법으로, 파이썬만의 고유 문법이 아니라 문자열을 처리하는

모든 곳에서 사용하는 일종의 형식 언어이다. 정규 표현식을 배우는 것은 파이썬을 배우는 것과는 또 다른 영역이다.

다음과 같은 문제가 주어졌다고 가정해 보자.

주민등록번호를 포함하고 있는 텍스트가 있다. 이 텍스트에 포함된 모든 주민등록번호의 뒷자리를 * 문자로 변경해 보자.

 

우선 정규식을 모른다면 다음과 같은 순서로 프로그램을 작성해야 할 것이다.

 

1. 전체 텍스트를 공백 문자로 나눈다.(split)

2. 나뉜 단어가 주민등록번호 형식인지 조사한다.

3. 단어가 주민등록번호 형식이라면 뒷자리를 *로 변환한다.

4. 나뉜 단어를 다시 조립한다.

 

이를 구현한 코드는 다음과 같을 것이다.

## 주민등록번호 뒷자리 *문자로 변경
data = """
park 088905-1049118
kim 700905-1059119
"""

result = []
for line in data.split("\n"):
    word_result = []
    for word in line.split(" "):
        if len(word) == 14 and word[:6].isdigit() and word[7:].isdigit():
            word = word[:6] + "-" + "*******"
        word_result.append(word)
    result.append(" ".join(word_result))
print("\n".join(result))
→ park 088905-*******
→ kim 700905-*******
 

 

반면, 정규식을 사용하면 다음처럼 훨씬 간편하고 직관적인 코드를 작성할 수 있다.

아직 정규식 사용 방법을 배우지 않았으므로 눈으로만 살펴보자.

## 정규식을 사용하여 주민등록번호 뒷자리 *문자로 변경
import re
data = """
park 800905-1049118
kim 700905-1059119
"""

pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", data))
→ park 800905-*******
→ kim 700905-*******
 

정규 표현식을 사용하면 이렇게 코드가 상당히 간결해진다.

만약 찾으려는 문자열 또는 바꾸어야 할 문자열의 규칙이 매우 복잡하다면 정규식의 효용은 더 커지게 된다.

 

 

정규 표현식 시작하기

정규 표현식에서 사용하는 메타 문자에는 다음과 같은 것이 있다. ". ^ $ * + ? { } [ ] \ | ( )"

정규 표현식에 메타 문자를 사용하면 특별한 의미를 갖게 된다.

 

○ 문자 클래스 [ ]

 

우리가 가장 먼저 살펴볼 메타 문자는 바로 문자 클래스인 [ ]이다.

문자 클래스로 만들어진 정규식은 "[’ 와 ‘]’ 사이의 문자들과 매치"라는 의미를 갖는다.

문자 클래스를 만드는 메타 문자인 [ ] 사이에는 어떤 문자도 들어갈 수 있다.

즉, 정규 표현식이 [abc]라면 이 표현식의 의미는 "a, b, c중 한 개의 문자와 매치"를 뜻한다.

이해를 돕기 위해 문자열 'a', 'before', 'dude'가 정규식 [abc]와 어떻게 매치되는지 살펴보자.

 

  • 'a'는 정규식과 일치하는 문자인 'a'가 있으므로 매치된다.
  • 'before'는 정규식과 일치하는 문자인 'b'가 있으므로 매치된다.
  • 'dude'는 정규식과 일치하는 문자인 a, b, c 중 어느 하나도 포함하고 있지 않으므로 매치되지 않는다.

 

[ ] 안의 두 문자 사이에 하이픈(-)을 사용하면 두 문자 사이의 범위를 의미한다.

예를 들어 [a-c]라는 정규 표현식은 [abc]와 동일하고 [0-5]는 [012345]와 동일하다.

다음은 하이픈(-)을 사용한 문자 클래스의 사용 예이다.

 

[a-zA-Z] : 모든 알파벳, [0-9] : 모든 숫자

문자 클래스[ ] 안에는 어떤 문자나 메타 문자도 사용할 수 있지만, 주의해야 할 메타 문자가 1가지 있다.

그것은 바로 ^인데, 문자 클래스 안에 ^ 메타 문자를 사용할 경우에는 반대(not)라는 의미를 갖는다.

예를 들어 [^0-9]라는 정규 표현식은 숫자가 아닌 문자만 매치된다.

 

자주 사용하는 문자 클래스를 살펴보자.

아래 표를 확인하면 대문자로 사용된 것은 소문자의 반대임을 추측할 수 있다.

 
정규 표현식
설명
\ d
숫자와 매치, [0-9]와 동일한 표현식이다.
\ D
숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식이다.
\ s
whitespace 문자(space나 tab처럼 공백을 표현하는 문자)와 매치
[ \t\n\r\f\v]와 동일한 표현식이다. 맨 앞의 빈칸은 공백 문자(space)를 의미한다.
\ S
whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식이다.
\ w
문자+숫자와 매치, [a-zA-Z0-9_]와 동일한 표현식이다.
\ W
문자+숫자가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식이다.

 

○ Dot(.)

정규 표현식의 .(dot) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치된다는 것을 의미한다.

다음 정규식을 살펴보자. a.b 이 정규식은 "a + 모든_문자 + b"의 의미와 같다.

즉, a와 b라는 문자 사이에 어떤 문자가 들어가도 모두 매치된다는 의미이다.

 

이해를 돕기 위해 문자열"aab", "a0b", "abc"가 정규식 a.b와 어떻게 매치되는지 살펴보자.

  • "aab"는 가운데 문자 'a'가 모든 문자를 의미하는 .과 일치하므로 정규식과 매치된다.
  • "a0b"는 가운데 문자 '0'가 모든 문자를 의미하는 .과 일치하므로 정규식과 매치된다.
  • "abc"는 "a"문자와 'b'문자 사이에 어떤 문자라도 하나는 있어야 하는 이 정규식과 일치하지 않으므로 매치되지 않는다.

 

앞의 식과 조금 다른 다음 정규식을 살펴보자. a[ . ]b

이렇게 [ ] 안에 dot(.) 문자를 쓰면 여기서 dot(.)은 메타 문자가 아니라 ‘.’ 문자 그대로를 의미한다.

즉, 이 정규식의 의미는 다음과 같다. "a + . + b"

따라서 정규식 a[ . ]b는 "a.b"문자열과 매치되고 "a0b"문자열과는 매치되지 않는다. 혼동하지 않도록 주의하자.

 

 

○ 반복(*)

다음 정규식을 살펴보자. ca*t

이 정규식은 반복을 의미하는 * 메타 문자를 사용했다.

여기에서 사용한 *은 * 바로 앞에 있는 문자 a가 0부터 무한대까지 반복될 수 있다는 의미이다.

 

※* 메타 문자의 반복 개수가 무한대라고 표현했는데, 메모리 용량에 한계가 있어 실제로는 약 2억 개라고 한다.

 

즉, 다음과 같은 문자열이 모두 매치된다.

  • "ct"는 'a'가 0번 반복되어 매치
  • "cat"는 'a'가 1번 반복되어 매치
  • "caaat"는 'a'가 3번 반복되어 매치

 

 

○ 반복(+)

반복을 나타내는 또 다른 메타 문자로 +가 있다. +는 최소 1번 이상 반복될 때 사용한다.

즉, *가 반복 횟수가 0부터라면 +는 반복 횟수가 1부터인 것이다. 다음 정규식을 살펴보자. ca+t

위 정규식은 "c + a가_1번_이상_반복 + t" 의미한다.

정규식의 매치 여부를 확인해 보겠다.

  • "ct"는 'a'가 0번 반복되어 매치되지 않음
  • "cat"는 'a'가 1번 반복되어 매치
  • "caaat"는 'a'가 3번 반복되어 매치

 

 

{ } 문자와 ? 문자

반복 횟수를 3회만 또는 1회부터 3회까지만으로 제한하고 싶다면 { } 메타 문자를 사용하여 반복 횟수를 고정할 수 있다.

{m, n} 정규식을 사용하면 반복 횟수가 m부터 n까지인 문자와 매치할 수 있다. m 또는 n을 생략할 수도 있다.

만약 {3,}처럼 사용하면 반복 횟수가 3 이상인 경우이고 {, 3}처럼 사용하면 반복 횟수가 3 이하인 경우를 의미한다.

생략된 m은 0과 동일하며, 생략된 n은 무한대(약 2억 개 미만)의 의미를 갖는다.

 

1. {m}사용

정규식 ca{2}t는 'a'가 2번 반복되면 매치"라는 의미이다.

  • "cat" 'a'가 1번 반복되어 매치되지 않음
  • "caat" 'a'가 2번 반복되어 매치

 

2. {m, n}사용

정규식 ca{2, 5}t는 "a가 2~5번 반복되면 매치"라는 의미이다.

  • "cat"는 'a'가 1번 반복되어 매치되지 않음
  • "caat"는 'a'가 2번 반복되어 매치
  • "caaat"는 'a'가 3번 반복되어 매치

 

3. ?사용

반복은 아니지만 이와 비슷한 기능을 하는 ? 문자가 있다. ? 메타 문자가 의미하는 것은 {0, 1}이다. 다음 정규식을 살펴보자.

ab?c의 의미는 "a + 'b가 있어도 되고 없어도 됨' + c" 여기서 'b가 0~1번 사용되면 매치'라는 의미이다.

  • "abc"는 'b'가 1번 사용되어 매치
  • "ac" 'b'가 0번 사용되어 매치

즉, b문자가 있거나 없거나 둘 다 매치되는 경우이다.

 

*, +, ? 메타 문자는 모두 {m, n} 형태로 고쳐 쓰는 것이 가능하다.

하지만, 이해하기 쉽고 표현도 간결한 *, +, ? 메타 문자를 사용하는 것이 좋다.

 

 

파이썬에서 정규 표현식을 지원하는 re 모듈

파이썬은 정규 표현식을 지원하기 위해 re(regular expression) 모듈을 제공한다.

re 모듈은 파이썬을 설치할 때 자동으로 설치되는 표준 라이브러리로, 사용 방법은 다음과 같다.

 

re.compile을 사용하여 정규 표현식(위 예에서는 ab*)을 컴파일한다.

re.compile의 리턴값을 객체 p(컴파일된 패턴 객체)에 할당해 그 이후의 작업을 수행할 것이다.

## re 모듈 사용 방법
import re
p = re.compile('ab*')
 

 

정규식을 이용한 문자열 검색

 

이제 컴파일된 패턴 객체를 사용하여 문자열 검색을 사용해 보자. 컴파일된 패턴 객체는 다음과 같은 4가지 메서드를 제공한다.

 
Method
목적
match()
문자열의 처음부터 정규식과 매치되는지 조사한다.
search()
문자열 전체를 검색하여 정규식과 매치되는지 조사한다.
findall()
정규식과 매치되는 모든 문자열(substring)을 리스트로 리턴한다.
finditer()
정규식과 매치되는 모든 문자열(substring)을 반복 가능한 객체로 리턴한다.

 

match, search는 정규식과 매치될 때는 match 객체를 리턴하고 매치되지 않을 때는 None을 리턴한다.

match 객체란 정규식의 검색 결과로 리턴된 객체를 말한다.

 

먼저 다음과 같은 패턴을 만들어 보자.

## 패턴 만들기
import re
p = re.compile('[a-z]+')
 

이 패턴 객체로 앞에 나온 메서드를 사용하는 간단한 예시를 작성할 것이다.

 

○ match 활용

match 메서드는 문자열의 처음부터 정규식과 매치되는지 조사한다. 앞 패턴에 match 메서드를 사용해 보자.

"python" 문자열은 [a-z]+ 정규식에 부합되므로 match 객체가 리턴된다.

## match 활용하기
import re
p = re.compile('[a-z]+')
m = p.match("python")
print(m)
→ <re.Match object; span=(0, 6), match='python'>
 

 

"python"을 "3 python"문자열로 바꾸어 실행해 보면 문자 '3'이 [a-z]+에 부합되지 않으므로 None이 리턴된다.

## match 활용하기2
import re
p = re.compile('[a-z]+')
m = p.match("3 python")
print(m)
→ None
 

 

match 메서드는 일치하는 결과가 있으면 match 객체를, 없으면 None을 리턴하므로

일반적인 파이썬 정규식 프로그램은 다음과 같은 흐름으로 작성한다.

즉, match의 결괏값이 있을 때만 그다음 작업을 수행하겠다는 것이다.

## match 활용하기3
import re
p = re.compile(정규 표현식)
m = p.match("조사할 문자열")
if m:
    print('Match found: ', m.group())
else:
    print('No match')
 

 

○ search 활용

컴파일된 패턴 객체 p를 가지고 이번에는 search 메서드를 사용해 보자.

"python" 문자열에 search 메서드를 수행하면 match 메서드를 수행했을 때와 동일하게 매치된다.

## search 활용하기1
import re
p = re.compile('[a-z]+')
m = p.search("python")
print(m)
→ <re.Match object; span=(0, 6), match='python'>
 

 

"python"을 "3 python"문자열로 바꾸어 실행하면 첫 번째 문자는 "3"이지만,

search는 문자열의 처음부터 검색하는 것이 아니라 문자열 전체를 검색하기 때문에 "3" 이후의 "python" 문자열과 매치된다.

## search 활용하기2
import re
p = re.compile('[a-z]+')
m = p.search("3 python")
print(m)
→ <re.Match object; span=(2, 8), match='python'>
 

이렇듯 match 메서드와 search 메서드는 문자열의 처음부터 검색할지의 여부에 따라 다르게 사용해야 한다.

 

 

○ findall 활용

이번에는 findall 메서드를 사용해 보자. findall은 패턴([a-z]+)과 매치되는 모든 값을 찾아 리스트로 리턴한다.

## findall 활용하기
import re
p = re.compile('[a-z]+')
result = p.findall("life is too short")
print(result)
→ ['life', 'is', 'too', 'short']
 

 

○ finditer 활용

이번에는 finditer 메서드를 사용해 보자. finditer는 findall과 동일하지만, 그 결과로 반복 가능한 객체를 리턴한다.

그리고 반복 가능한 객체가 포함하는 각각의 요소는 match 객체이다.

## finditer 활용하기
import re
p = re.compile('[a-z]+')
result = p.finditer("life is too short")
print(result)
for r in result: print(r)
→ <callable_iterator object at 0x000001E369E0BCA0>
→ <re.Match object; span=(0, 4), match='life'>
→ <re.Match object; span=(5, 7), match='is'>
→ <re.Match object; span=(8, 11), match='too'>
→ <re.Match object; span=(12, 17), match='short'>
 

 

match 객체의 메서드

match 객체란 앞에서 살펴본 p.match, p.search 또는 p.finditer 메서드에 의해 리턴된 매치 객체를 의미한다.

이제 이 match 객체에 대해서 자세히 알아보자.

앞에서 정규식을 사용한 문자열 검색을 수행하면서 매치된 문자열의 종류 또는 매치된 문자열의 인덱스의 구간이 궁금할 수 있다.

match 객체의 메서드를 사용하면 이 같은 궁금증을 해결할 수 있다. 다음 표를 살펴보자.

 
method
목적
group
매치된 문자열을 리턴한다.
start
매치된 문자열의 시작 위치를 리턴한다.
end
매치된 문자열의 끝 위치를 리턴한다.
span
매치된 문자열의 (시작, 끝)에 해당하는 튜플을 리턴한다.

 

다음 예로 확인해 보자.

예상한 대로 결괏값이 출력되는 것을 확인할 수 있다. match 메서드를 수행한 결과로 리턴된 match 객체로

start 메서드를 사용했을 때 결괏값은 항상 0일 수밖에 없다. match 메서드는 항상 문자열의 시작부터 조사하기 때문이다.

## match 객체의 메서드 예시
import re
p = re.compile('[a-z]+')
m = p.match("python")
m.group()
→ "python"
m.start()
→ 0
m.end()
→ 6
m.span()
→ (0, 6)
 

 

컴파일 옵션

정규식을 컴파일할 때 다음 옵션을 사용할 수 있다. 표를 확인해 보자.

옵션을 사용할 때는 re.DOTALL처럼 전체 옵션 이름을 써도 되고 re.S처럼 약어를 써도 된다.

 
옵션 이름
약어
설명
DOTALL
S
dot 문자(.)가 줄바꿈 문자를 포함하여 모든 문자와 매치한다.
IGNORECASE
I
대,소문자에 관계 없이 매치한다.
MULTILINE
M
여러 줄과 매치한다.
(^, $ 메타 문자의 사용과 관계가 있는 옵션이다.)
VERBOSE
X
verbose 모드를 사용한다.
(정규식을 보기 편하게 만들 수도 있고 주석 등을 사용할 수도 있다.)

 

○ DOTALL 또는 S

'. '메타 문자는 줄바꿈 문자(\n)를 제외한 모든 문자와 매치되는 규칙이 있다. 만약 \n 문자도 포함하여 매치하고 싶다면

re.DOTALL 또는 re.S 옵션을 사용해 정규식을 컴파일하면 된다. 다음 예를 보자.

정규식이 a.b인 경우 문자열 a\nb는 매치되지 않는다는 것을 알 수 있다. \n은 '.' 메타 문자와 매치되지 않기 때문이다.

## '.'메타 문자 매치 예제
import re
p = re.compile('a.b')
m = p.match("a\nb")
print(m)
→ None
 

 

\n 문자와도 매치되게 하려면 다음과 같이 re.DOTALL 옵션을 사용해야 한다.

보통 re.DOTALL 옵션은 여러 줄로 이루어진 문자열에서 줄바꿈 문자에 상관없이 검색할 때 많이 사용한다.

## DOTALL, S 예시
import re
p = re.compile('a.b', re.DOTALL)
m = p.match("a\nb")
print(m)
→ <re.Match object; span=(0, 3), match='a\nb'>
 

 

○ IGNORECASE 또는 I

re.IGNORECASE 또는 re.I 옵션은 대소문자 구별 없이 매치를 수행할 때 사용하는 옵션이다. 다음 예제를 살펴보자.

[a-z]+ 정규식은 소문자만을 의미하지만, re.I 옵션으로 대소문자 구별 없이 매치된다.

## IGNORECASE, I 예시
import re
p = re.compile('[a-z]+', re.I)
p.match('python')
→ <re.Match object; span=(0, 6), match='python'>
p.match('Python')
→ <re.Match object; span=(0, 6), match='Python'>
p.match('PYTHON')
→ <re.Match object; span=(0, 6), match='PYTHON'>
 

 

○ MULTILINE 또는 M

re.MULTILINE 또는 re.M 옵션은 조금 후에 설명할 메타 문자인 ^, $와 연관된 옵션이다.

이 메타 문자에 대해 간단히 설명하면 ^는 문자열의 처음, $는 문자열의 마지막을 의미한다.

예를 들어 정규식이 ^python인 경우, 문자열의 처음은 항상 python으로 시작해야 매치되고

만약 정규식이 python$이라면 문자열의 마지막은 항상 python으로 끝나야 매치된다는 의미이다.

 

다음 예를 살펴보자.

정규식 ^python\s\w+은 python이라는 문자열로 시작하고 그 뒤에 화이트스페이스, 그 뒤에 단어가 와야 한다는 의미이다.

이 코드를 실행하면 다음과 같은 결과를 리턴한다.

^메타 문자에 의해 python이라는 문자열을 사용한 첫 번째 줄만 매치된 것이다.

## 정규식 ^python\s\w+ 예시
import re
p = re.compile("^python\s\w+")
data = """python one
life is too short
python two
you need python
python three"""

print(p.findall(data))
→ ['python one']
 

 

하지만, ^메타 문자를 문자열 전체의 처음이 아니라 각 라인의 처음으로 인식시키고 싶은 경우도 있을 것이다.

이럴 때 사용할 수 있는 옵션이 바로 re.MULTILINE 또는 re.M이다. 위 코드를 다음과 같이 수정해 보자.

re.MULTILINE 옵션을 사용하면 ^ 메타 문자가 문자열 전체의 시작이 아닌 각 줄의 시작이라는 의미를 가지게 되었다.

 

즉, re.MULTILINE 옵션은 ^, $ 메타 문자를 문자열의 각 줄마다 적용해 주는 것이다.

## MULTILINE 예시
import re
p = re.compile("^python\s\w+", re.MULTILINE)
data = """python one
life is too short
python two
you need python
python three"""

print(p.findall(data))
→ ['python one', 'python two', 'python three']
 

 

○ VERBOSE 또는 X

지금껏 알아본 정규식은 매우 간단하지만, 정규식 경험이 많은 개발자들이 만든 정규식을 이해하려면 하나하나 이해해야만 한다.

이렇게 이해하기 어려운 정규식을 주석 또는 줄 단위로 구분할 수 있다면 이해하기 쉬울 것이다.

이 경우에는 re.VERBOSE 또는 re.X 옵션을 사용하면 된다. 다음 예를 보자.

tests의 첫 번째 문자열의 경우 10진수 문자 참조가 포함되어 있으므로 'Exist'이 출력된다.

반면, 두 번째 문자열은 문자 참조가 없기 때문에 'None'이 출력된다.

## 복잡한 정규식 예시
import re
charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')

tests = ["This is the letter A: &#65;",
        "Normal text without entity"
        ]

for text in tests:
    match = charref.search(text)
    if match:
        print("Exist")
    else:
        print("None")
→ Exist
→ None
 

이 정규식은 매우 복잡해 보인다. 다음 예제를 살펴보자.

## 복잡한 정규식 예시2
import re
charref = re.compile(r'''
&[#]                           # 문자 참조 시작(예: &# 또는 &#x)
(
    0[0-7]+                    # 8진수 참조(0으로 시작)
   |[0-9]+                     # 10진수 참조
   |x[0-9a-fA-F]+              # 16진수 참조(예: &#ㅌ41;)
)
;                              # 문장 마지막 세미콜론 참조
''', re.VERBOSE)

tests = ["This is the letter A: &#65;",
        "Normal text without entity"
        ]       

for text in tests:
    match = charref.search(text)
    if match:
        print("Exist")
    else:
        print("None")
→ Exist
→ None
 

첫 번째와 두 번째 예제는 동일한 정규식을 사용하지만, 두 번째 방식처럼 re.VERBOSE 옵션을 활용하면

복잡한 정규식을 줄 단위로 나누고 주석을 추가하여 훨씬 가독성이 좋게 만들 수 있다.

re.VERBOSE 옵션을 사용하면 정규식 내의 공백 문자는 컴파일 시 무시된다. (단, [ ] 안에 사용한 화이트스페이스는 제외)

 

백슬래시 문제

Python 정규 표현식

정규 표현식을 파이썬에서 사용할 때 혼란을 주는 요소가 1가지 있는데, 바로 백슬래시(\)이다.

예를 들어 어떤 파일 안에 있는 "\section" 문자열을 찾기 위한 정규식을 만든다고 가정해 보자.

이 정규식은 \s문자가 whitespace로 해석되어 의도한 대로 매치가 이루어지지 않는다.

 

이 표현은 다음과 동일한 의미이다. "[ \t\n\r\f\v]ection

의도한 대로 매치하고 싶다면 다음과 같이 변경해야 한다. "\\section"

즉, 앞 정규식에서 사용한 '\'문자가 문자열 자체라는 것을 알려 주기 위해 백슬래시 2개를 사용해 이스케이프를 처리해야 한다.

 

따라서 위 정규식을 컴파일하려면 다음과 같이 작성해야 한다.

"p = re.compile('\\section')"

그런데 여기에서 또 하나의 문제가 발견된다. 이처럼 정규식을 만들어서 컴파일하면 실제 파이썬 정규식 엔진에는

파이썬 문자열 리터럴 규칙에 따라 \\이 \로 변경되어 \section이 전달된다.

결국 정규식 엔진에 \\ 문자를 전달하려면 파이썬은 \\\\처럼 백 슬래시를 4개나 사용해야 한다.

 

※ 정규식 엔진은 정규식을 해석하고 수행하는 모듈이다.

 

만약 이와 같이 \를 사용한 표현이 계속 반복되는 정규식이라면 너무 복잡해서 이해하기 어려울 것이다.

이 문제를 해결하려면 raw string표현법을 사용해야 한다. 그 방법은 다음과 같다.

## raw string표현법
p = re.compile(r'\\section')
 

이와 같이 정규식 문자열 앞에 r 문자를 삽입하면 이 정규식은 raw string 규칙에 의해

백슬래시 2개 대신 1개만 써도 2개를 쓴 것과 동일한 의미를 가지게 된다.

 

만약 백슬래시를 사용하지 않는 정규식이라면 r의 유무에 상관없이 동일한 정규식이 될 것이다.

 

 

 

 

 

 

TEL (062-226-1777, 010-9891-7244), E-mail (ipmes@ipmes.co.kr)

임베디드 시스템 | PCB 설계 제작 | 펌웨어 개발 | 신호처리 | 응용프로그램