List
- 정규 표현식
- 정규 표현식 I
- 정규 표현식 II
※ 정규 표현식은 줄여서 간단히 "정규식"이라고도 말한다.
.^*+?{ }[ ]\( )문자클래스 [ ] : "[ ] 사이의 문자들과 매치"`
[ ] 사이에는 어떤 문자도 들어갈 수 있다. 문자 클래스 [ ] 사용법
[abc] = "a, b, c중 한 개의 문자와 매치"문자열 "a", "before", "dude"가 정규식 [abc]와 어떻게 매치되는가 ?
- "a"는 매치 # 정규식과 일치하는 문자 "a"가 있기 때문
- "before"은 매치 # 정규식과 일치하는 문자 "b"가 있기 떄문
- "dude" 는 매치불가 # 정규식과 일치하는 문자인 a,b,c중 아무것도 없기 떄문
[문자1-문자2] : [문자1(from)-문자2(to)]안 두문자 사이의 문자들과 매치"` - `[a-c]` = `[abc]`
- `[0-5]` = `[012345]`
- `[a-zA-Z]` = `[알파벳 모두]`
- `[0-9]` = `[0,1,2,3,4,5,6,7,8,9]`
[문자 클래스 사용시 주의할 점]
^: 문자 클래스 안에 매타 문자^를 사용할 경우에는 반대(not)라는 의미를 갖는다.[^0-9] = [0,1,2,3,4,5,6,7,8,9] 숫자가 아닌 문자와만 매치
[자주 사용하는 문자 클래스]
\d=[0-9]- 숫자와 매치\D=[^0-9]- 숫자가 아닌 것과 매치\s=[ \t\n\r\f\v]- whitespace 문자와 매치, 맨 앞의 빈 칸은공백문자(space)를 의미\S=[^ \t\n\r\f\v]- whitespace 문자가 아닌 것과 매치\w=[a-zA-Z0-9_]- 문자+숫자(alphanumeric와 매치\W=[^a-zA-Z0-9_]- 문자+숫자(alphanumeric)가 아닌 문자와 매치
Dot(.) : \n(줄바꿈 문자)를 제외한 모든문자와 매치re.DOTALL 옵션을 주면
\n과도 매치된다.
Dot(.) 사용법a.b= "a + 모든문자 + b", a와 b사이 어떤 문자가 들어가도 전부 매치된다.- "aab" 는 매치 # 가운데 문자 "a"가 모든 문자를 의미하는 .과 일치
- "a0b" 는 매치 # 가운데 문자 "0"가 모든 문자를 의미하는 .과 일치
- "abc"는 매치불가 # "a"문자와 "b"문자 사이에 문자가 하나도 없다.
Dot(.) 사용법 2a[.]b = "a + Dot(.)문자 + b", 문자 클래스 안에 . 이 있으므로 a와 b사이 무조건 .만 올수 있다. - "a.b"은 매치
- "a0b"은 매치불가
※ 만약
문자 클래스([])내에Dot(.) 메타 문자가 사용된다면 이것은 "모든 문자"라는 의미가 아닌 문자.그대로를 의미한다.
* : *바로 앞에 있는 문자가 0부터 무한대로 반복되야 매치* 사용법ca*t = *앞에있는 문자 a가 무한대로 반복 될수 있다.(반복이 없어도 매치되는거당)- "ct"는 매치 # "a"가 0번 반복
- "cat"는 매치 # "a"가 0번 이상 반복(1회 반복)
- "caaat"는 매치 # "a"가 0번 이상 반복(3회 반복)
+ : +바로 앞에 있는 문자가 최소 1번 이상 반복되야 매치+ 사용법 ca*t = +앞에있는 문자 a가 최소 1번 이상 될 수 있다.(0개 반복은 매치불가)- "ct"는 매치불가 # "a"가 0번 반복
- "cat"는 매치 # "a"가 1번 이상 반복(1회 반복)
- "caaat"는 매치 # "a"가 1번 이상 반복(3회 반복)
즉
*는 반복 횟수 0부터 /+는 반복 횟수 1부터 인 것이다.
반복 ({m,n}, ?) : 반복 횟수를 고정하 수 있다.
{1,3} : 1 ~ 3 반복{3,} : 반복 횟수 3 이상{,3} : 반복 횟수 3 이하즉
{1,}=+,{0,}=*
반복 ({m,n}, ?) 사용법
{m} = 반드시 m 번 반복
ca{2}t = "c + a(반드시 2번 반복) + t"-"cat" 는 매치불가 # "a"가 1번 반복
-"caat" 는 매치 # "a"가 2번 반복
{m, n} = m~n반복
ca{2,5}t = "c + a(2~5회 반복) + t"-"cat" 는 일치 불가 # "a"가 1번만 반복
-"caat" 는 일치 # "a"가 2번 반복
-"caaaaat"는 일치 # "a"가 5번 반복
? = {0, 1}
ab?c = "a + b(있어도 되고 없어도 된다) + c"- "abc"는 매치 # "b"가 1번 사용
- "ac"는 매치 # "b"가 0번 사용
** 이 자체가 패턴이당
>>> import re
>>> p = re.compile('ab*') # ab*를 컴파일 하고, 객체 p를 사용하여 이후 작업을 수행할 것이다
- 정규식을 컴파일할 때 특정 옵션을 주는 것도 가능
** 이 자체가 패턴이다.
>>> import re
>>> p = re.compile('[a-z]+')
match객체를 돌려주고,>>> m = p.match("python") # "python"은 "[a-z]+정규식과 매치 된다.
>>> print(m)
<_sre.SRE_Match object at 0x01F3F9F8> # 그렇기 때문에 match 객체(m)를 돌려준다None을 돌려준다,>>> m = p.match("3 python") # 숫자 3 때문에 매치불가
>>> print(m)
None # None을 돌려준다match()사용법 p = re.compile(정규표현식) # 여기 안에 정규 표현식이 들어가야지~[a-z]+ 이런거 ~
m = p.match( 'string goes here' )
if m: # match의 결괏값이 있을 때만 그다음 작업을 수행하겠다는 것
print('Match found: ', m.group())
else:
print('No match')
>>> m = p.search("python")
>>> print(m)
<_sre.SRE_Match object at 0x01F3FA68> # match 와 동일
>>> m = p.search("3 python")
>>> print(m)
<_sre.SRE_Match object at 0x01F3FA30> # match와 다름/ search는 문자열 전체를 검색하기 때문에 "3 " 이후의 "python" 문자열과 매치
match 메서드와search 메서드는 문자열의 처음부터 검색할지의 여부에 따라 다르게 사용해야 한다.
>>> result = p.findall("life is too short") # 문자열의 'life', 'is', 'too', 'short' 단어를 각각 [a-z]+ 정규식과 매치
>>> print(result)
['life', 'is', 'too', 'short'] # 전부 매치되서 결괏값 출력
>>> result = p.finditer("life is too short") #
>>> print(result)
<callable_iterator object at 0x01F5E390>
>>> for r in result: print(r)
...
<_sre.SRE_Match object at 0x01F3F9F8>
<_sre.SRE_Match object at 0x01F3FAD8>
<_sre.SRE_Match object at 0x01F3FAA0>
<_sre.SRE_Match object at 0x01F3F9F8>
- 즉
findall()과finditer()은 동일하다.- 결괏값을 출력하는 방법이 다를 뿐
findall()->리스트(list)로 출력finditer()->반복 가능한 객체(iterator object)로 출력
반복 가능한 객체의 각 요소들은match 객체이다.
match()와 search()객체의 매서드group() : 매치된 문자열을 돌려준다.start() : 매치된 문자열의 시작 위치를 돌려준다.end() : 매치된 문자열의 끝 위치를 돌려준다.span() : 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려준다.>>> m = p.match("python")
>>> m.group()
'python'
>>> m.start() # 슬라이싱 개념으로 생각하자.
0
>>> m.end() # 슬라이싱 개념으로 생각하자.
6
>>> m.span() # 슬라이싱 개념으로 생각하자.
(0, 6)
>>> m = p.search("3 python")
>>> m.group()
'python'
>>> m.start() # 딱 python만 가지고 오는거지, 슬라이싱개 개념으로 생각하자
2
>>> m.end() # 딱 python만 가지고 오는거지, 슬라이싱개 개념으로 생각하자
8
>>> m.span() # 딱 python만 가지고 오는거지, 슬라이싱개 개념으로 생각하자
(2, 8)
[모듈 단위로 수행]
re 모듈축약 해보자 ㅡ ㅡ>> p = re.compile('[a-z]+') >> m = p.match("python")>> m = re.match('[a-z]+', "python")
- 보통 한 번 만든 패턴 객체를 여러번 사용해야 할 때는 이 방법보다
re.compile을 사용하는 것이 편하다.
re.DOTALL = re.S. 메타문자에 \n는 제외되지만, \n을 포함 시키고 싶다면 re.DOTALL 또는 re.S 옵션을 줘라>>> import re
>>> p = re.compile('a.b')
>>> m = p.match('a\nb') # 메타문자 . 을 사용했을 때 \n 은 매치 되지 않는다
>>> print(m)
Nonere.DOTALL 옵션 사용>>> p = re.compile('a.b', re.DOTALL) # re.DOTALL 과 re.S 아무거나 사용하면 됌
>>> m = p.match('a\nb')
>>> print(m)
<_sre.SRE_Match object at 0x01FCF3D8>re.IGNORECASE = re.I>>> p = re.compile('[a-z]', re.I) # [a-z]은 소문자만 의미 / re.I 옵션으로 대소문자 구별없이 매치
>>> p.match('python')
<_sre.SRE_Match object at 0x01FCFA30>
>>> p.match('Python')
<_sre.SRE_Match object at 0x01FCFA68>
>>> p.match('PYTHON')
<_sre.SRE_Match object at
0x01FCF9F8>re.MULTILINE = re.M^, $ 와 연관이 있다.[
^,$의 사용]
^는 문자열의 처음을 의미
^python ~인 경우, 문자열의 처음은 항상 python으로 시작해야 매치된다.$는 문자열의 마지막을 의미
~ python$인 경우, 문자열의 마지막은 항상 python으로 끝나야 매치된다.
import re
p = re.compile("^python\s\w+") # "python"이라는 문자열로 시작, 그 뒤 "whitespace", 그 뒤 "단어"
data = """python one # data 는 여러 줄로 이루어져 있음
life is too short
python two
you need python
python three"""
print(p.findall(data))
['python one'] # 메타 문자 "^" 때문 python으로 시작하는 문자열인 첫번째 문자열만 출력
import re
p = re.compile("^python\s\w+", re.MULTILINE) # 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']
re.VERBOSE = re.Xcharref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')charref = re.compile(r"""
&[#] # Start of a numeric entity reference
(
0[0-7]+ # Octal form
| [0-9]+ # Decimal form
| x[0-9a-fA-F]+ # Hexadecimal form
)
; # Trailing semicolon
""", re.VERBOSE)
p = re.compile(r'\\section')
r'활용
- 컴파일해야 하는 정규식이 Raw String임을 알려주는 파이썬 문법
- 위와 같이 진행 시
\section을 찾도록 해준당
p = re.compile('\\\\section')p = re.compile('\section')\section = [ \t\n\r\f\v]ection\를 한번 썻을 떄 앞의 \s는 whitespace로 해석되어 원하는 게 나오지 않는다.p = re.compile('\\section')\\ 사용하여 이스케이프 처리 시도 머리좀 씀\\이 \로 변경되어 \section이 전달된다.p = re.compile('\section') 이럭게 된당