
Regular Expression : 정규표현식 요약
Regular Expression (re) 의 기본적인 operator는 다음과 같음.
| Basic operator | Description |
| . | Any character except `\n` (newline) |
| a | The character a itself |
| ab | The string ab itself |
| x|y | x or y |
| \y | Escapes a special character y, such as ^+{}$()[]|\-?.* |
- backslash 는 escape sequence로 동작을 의미함 :
- 즉, 뒤에 오는 문자와 결합하여 newline이나 tab등을 의미하게 됨.
- 반대로 특수한 의미를 가지는 문자들(^+{}$()[]|\-?.*)이 backslash 뒤에 오면, 자신의 특수한 의미를 잃고 그 문자 자체를 의미: 이는 ERE 의 경우에 해당하며 자세한 건 아래 bullet list를 참고!
- BRE (Basic Regular Expression) 에서 metacharacter는 ^, $, ( , ) , . , * 임.
- ERE (Extended Regular Expression)에서 + , ( , ) , { , } , | , ? 가 추가됨
- BRE 에서도 ERE의 metacharacters를 사용하는 경우는 backslash \ 를 추가해서 사용함.
- ERE 에선 위의 설명처럼 backslash를 prefix로 사용하는 경우엔 literal character로 사용되고 단독으로 사용시 metachracter 로 처리됨.
- 참고로 일반적으로 쉘 등에서 사용되는 경우, expansion등을 피하기 위해 quoting 을 해주는게 일반적임.
- a 글자 그대로를 가르킨다는 것은 a 라고 기재된 literal character 을 의미한다는 것임.
- BRE와 ERE 모두 POSIX 기반임.
https://gist.github.com/dsaint31x/24fcc0abb68855518da917771dcd2c1a
re_regular_expression.ipynb
re_regular_expression.ipynb. GitHub Gist: instantly share code, notes, and snippets.
gist.github.com
기본 Escape Sequence
기본적인 escape sequence들의 예는 다음과 같음.
| Escaped characters (or Escaped sequence) | name |
| \n | Newline |
| \r | Carriage return |
| \t | Tab |
- 사실 backslash는 Python에서 escape character라고 불림.
- 그 뒤에 놓이는 character가 본래 가지는 기능에서 escape시킨다고 생각할 수 있음.
- backslash 자체를 출력하기 위해서는 \\ 를 사용. (escape하는 기능에서 escape?)
- raw string에서는 backslash가 일반 글자로 처리됨 :
다음의 두 라인은 모두 backslash를 글자 자체로 처리 하여 출력하고, 그 뒤에 n이 놓임.
'\\n'
r'\n'
여기서 raw string을 다룬 이유는
RE의 expression들은 backslash를 매우 빈번하게 사용하기 때문에,
Python의 경우 re 모듈을 사용할 때, pattern을 표현하는 문자열은
기본 escape sequence와 충돌을 피하기 위해
raw string을 사용하는 경우가 일반적이기 때문임.
Regular Expression에서의 Character Classes
RE의 기본 character classes는 다음과 같음.
| Character classes | Description |
| [a-d] | One character of: a,b,c,d (문자클래스) 정확히는 a or b or c or d a|b|c|d BRE에서도 사용되는 bracket expression |
| [^a-d] | One character except: a,b,c,d not (a or b or c or d) BRE에서도 사용되는 bracket expression |
| \d | One digit, PCRE |
| \D | One non-digit, PCRE |
| \s | One whitespace character, PCRE |
| \S | One non-whitespace, PCRE |
| \w | One alphanumeric character, PCRE |
| \W | One non-alphanumeric character, PCRE |
- square bracket은 하나의 글자(character)를 의미
- square bracket안의 dash는 범위를 의미(알파벳 순).
- square bracket안의 caret은 complement를 의미하여 "여집합"을 의미하게 됨.
- d 는 digit으로 숫자를 의미하고, 대문자 D 는 Non digit을 의미함.
- 주로, 대문자는 Non (~Complement, Negation)을 의미한다.
Basic Regular Expression (BRE) 나 ERE는 일반 CLI 툴들에서 거의 지원을 하지만, 보다 확장된 Perl Compatible Regular Expression (PCRE)가 최근의 SW나 프로그래밍 언어 등의 RE모듈에서 많이 사용됨.
엄밀하게 애기하면 Python의 re모듈은 CPython에 구현된 Simple Regular Expression 엔진으로 PCRE 엔진은 아니나 사용하는 문법은 비슷함.
Python의 string의 printable을 통해 위의 character classes를 확인해보는 코드는 다음과 같음.
# cell_id: 3En6W1VTURCx
import string
import re
printable = string.printable
print(f'len of printable {len(printable)}')
print(f'{type(printable) = }')
print(f'{printable}')
len of printable 100
type(printable) = <class 'str'>
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
# cell_id: Nubg8rI6UVUM
print('-------------------')
print('digits')
print(re.findall(r'\d', printable)) # raw string을 사용하지 않을 경우 warning.
-------------------
digits
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
# cell_id: M_kpKeNDUbNA
print('white space')
# space, tab, newline, carriage return, vertical tab, and form feed.
print(re.findall(r'\s', printable))
white space
[' ', '\t', '\n', '\r', '\x0b', '\x0c']
# cell_id: RWuZXWfFUfGE
print('alphanumeric')
print(re.findall(r'\w', printable))
alphanumeric
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_']
# cell_id: mWwgCeV3UjvD
# -----------------------
# Test for unicode
x = 'abc' + '-/*' + '\u00ea' + '\u0115'
print(x)
abc-/*êĕ
# cell_id: 0tlUwRDOUpzq
tmp = re.findall(r'\w', x)
print(f"{type(tmp) = }")
tmp
type(tmp) = <class 'list'>
['a', 'b', 'c', 'ê', 'ĕ']
# cell_id: -tEC2DMBU2rP
print(re.findall(r'\W', x))
['-', '/', '*']
RE's Quantifiers
RE의 기본 Quantifiers (반복횟수, 갯수 등을 지정)은 다음과 같음.
| Quantifiers | Description |
| x* | Zero or more xs |
| x+ | One or more xs |
| x? | Zero or one x (=Optional of the preceding character) |
| x{2} | Exactly two xs |
| x{2,5} | Between two and five xs |
- 앞서 살펴본 문자나 숫자들이 몇번 나타나는지 등등의 지정이 위의 Quantifier를 통해 수행됨.
아래 내용들은 정규표현식에 대한 좀 더 세부 내용이나,
위의 내용들은 기본적 상식으로 알고 있는 게 좋은 것들로 차이가 있음
RE's Assertion
다음은 RE의 Assertion들로
실제로 다른 문자열을 매칭시키지 않으면서 그 자리에서 앞이나 뒤에 해당하는 패턴이 존재하는 지만 확인 (확인만 할 뿐 해당 부분은 matching에 포함되지 않음) 하는 방식으로 동작.
| Assertions | Description |
| ^ | Start of string, Caret |
| \b | Word boundary (between a \w and a \W, in either order) |
| \B | Non-word boundary |
| $ | End of string, Dollar sign |
| prev (?= next ) | prev if followed by next |
| (?<= prev ) next | next if preceded by prev |
| (?<! prev ) next | next if not preceded by prev |
- 주의할 점은 \b 가 Python의 string에서 escape sequence로 backspace이라는 점임..
- 하지만 RE에서는 한 단어의 시작을 의미함.
- 이를 제대로 동작시키기 위해서는 앞서 살펴본대로 raw string으로 처리해야 한다.
assertion이라는 뜻은
참이라고 단정(assert)하는 조건/주장을 가리킴.
프로그래밍에서 assertion이란?
특정 조건이 여기선
반드시 참이어야 함 을 확인(데이터를 바꾸거나 데이터를 소비하지 않음=커서이동 x)만 하는 동작
을 가리킴
즉, 프로그램의 동작 흐름에 영향을 주지않고 확인만 하는 형태임
(물론 참이 아닌 경우엔 동작을 중지시키고 개발자에게 알림)
다음 예제를 확인하라.
# cell_id: LlQqgXl3U442
source = '''I wish I may, I wish I might
Have a dish of fish tonight.
I love a dish of fish foreever'''
print(source)
print('===============')
print(re.findall('^I wish', source))
print(re.findall('^wish', source))
print(re.findall('I (?=wish)', source))
print(re.findall('(?<=I) wish', source))
print('===============')
print(re.findall('\bfish', source)) # backspace로 해석됨
print(re.findall(r'\bfish', source))
I wish I may, I wish I might
Have a dish of fish tonight.
I love a dish of fish foreever
===============
['I wish']
[]
['I ', 'I ']
[' wish', ' wish']
===============
[]
['fish', 'fish']
RE's Group
다음은 RE에서 group을 지정하는 방법을 보여줌.
| Groups | Description |
| (x) | Capturing group (matching된 반환값에 포함됨.) |
| (?:x) | Non-capturing group (matching에서는사용되나 반환값에 포함되지 않음) |
- RE에서 해석되는 우선순위 등을 조절하기 위해 Group으로 묶는 경우도 있음.
- RE가 반환하는 match된 문자열들도 지정한 group으로 나누어질 수 있음.
다음은 group이 RE의 output에 미치는 영향을 간략히 보여줌.
# 일치하는 부분이 있으면 Match 객체를 반환하고, 없으면 None을 반환
# 첫번째만 반환하므로, 모든 일치하는 부분을 구하려면 finditer()를 사용.
m = re.search(r'(. dish\b).*(\bfish)', source)
print(f"{type(m) = }")
print(f"{m = }")
# matching 이 이루어진 문자열을 반환.
g = m.group()
print(f"{type(g) = }")
print(f"{g = }")
# capture group들을 tuple로 묶어서 반환.
# parentheses로 capture group이 이 예에선 2개임.
gl = m.groups() # list로 RE로 지정한 그룹이 나누어 들어감.
print(f"{type(gl) = }")
print(f"{gl = }")
type(m) = <class 're.Match'>
m = <re.Match object; span=(34, 48), match='a dish of fish'>
type(g) = <class 'str'>
g = 'a dish of fish'
type(gl) = <class 'tuple'>
gl = ('a dish', 'fish')
다음은 복수 개의 group에 접근하는 finditer 에 대한 예제코드임
m_iter = re.finditer(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)', source)
for idx, m in enumerate(m_iter):
print(f'match {idx} ========')
print(m.group())
print(m.group('DISH')) # 지정한 이름으로 group접근.
print(m.group('FISH'))
match 0 ========
a dish of fish
a dish
fish
match 1 ========
a dish of fish
a dish
fish
그룹 이름 지정.
다음은 RE가 여러 문자열을 반환하는 경우 접근을 쉽게하기 위해 이름을 지정하는 방법을 보여줌.
| Naming | Description |
| (?P<name> expr) | match expr, saving the match in group name |
- expr 에 해당하는 expression에 매칭된 그룹의 이름이 name이 된다.
다음 예를 확인하라.
m = re.search(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)', source)
print(m.group())
print(m.group('DISH')) # 지정한 이름으로 group접근.
print(m.group('FISH'))
a dish of fish
a dish
fish
참고: File-glob 패턴과의 차이점
File-glob 패턴은 정규표현식(Regular Expression)의 하위집합이라기보다는,
“파일 이름 매칭에 특화된 단순한 패턴 매칭 문법”이며,
그 개념은 정규표현식과 유사하지만 별도의 문법 체계임.
Python에서도 glob과 regex는 완전히 다른 모듈로 지원됨.
- glob.glob() → glob 패턴
- re.match() → regex 패턴
같이 보면 좋은 자료들
https://dsaint31.tistory.com/548
[Python] Regular Expression : re 요약
Regular Expression : re 요약 정규표현식(正規表現式, Regular Expression)은문자열을 처리하는 방법 중의 하나로특정한 조건의 substring(문자열)을 'searching(검색)'하거나 'substition(치환)'하는 과정을특정 문
dsaint31.tistory.com
glob 이란?
정의glob은 파일 이름과 경로를 간단한 와일드카드 패턴으로 매칭하는 방식을 가리킴. Bash, zsh 등의 shell 과 여러 프로그래밍 언어(Python의 glob 모듈 등)에서 폴더 내 파일을 찾거나 일괄 처리할 때
ds31x.tistory.com
2026.02.18 - [utils] - Vim Regular Expression
Vim Regular Expression
Vim Regular ExpressionVim에서의 RE(Regular Expression) 은 Python이나 C에서의 RE 와 조금 차이가 있다.참고로 Vim의 RE는 backslash가 무지 많이 요구되기 때문에,일반적으로 very magic 모드(\v)를 사용하는 게 정신
ds31x.tistory.com
'Python' 카테고리의 다른 글
| [Python] binary file: write and read (0) | 2023.07.04 |
|---|---|
| [Python] Text File: read and write (0) | 2023.07.04 |
| [Python] file: open and close (0) | 2023.07.04 |
| [Python] venv : Python Virtual Environment (0) | 2023.06.30 |
| [Python] pip 사용법 (0) | 2023.06.30 |