점프 투 파이썬 5

김지용·2022년 8월 24일
0

독서

목록 보기
3/11
post-thumbnail

프로그래밍 정규식
정규효현식, 컴파일옵션, RawString

파이썬 실력 키우기

프로그램을 만들려면 먼저 '입력'과 '출력'을 생각하라! (271p~287p)

  • 3과 5의 배수 합하기
result = 0
for n in range(1, 1000):
    if n%3==0 or n%5==0:
        result += n
print(result)
  • 게시판 페이징하기
  • 간단한 메모장 만들기
  • 탭을 4개의 공백으로 바꾸기 ("\t") == (tap) (287p)
space_content = tab_content.replace("\t", " "*4)

f = open(dst, 'w')
f.write(space_content)
f.close()

(288~291p)

  • 하위 디렉토리 검색하기
    os.walk 는 시작 디렉토리부터 그 하위 모든 디렉토리를 차례대로 방문하게 해주는 함수이다.

(292~293p) 문제풀이 (반복 문자열 표시, defaultdict 같은 패키지 사용없이 풀어보기)

def compress_string(s):
    _c = ""
    cnt = 0
    result = ""
    for c in s:
        if c!=_c:
            _c = c
            if cnt: result += str(cnt)
            result += c
            cnt = 1
        else:
            cnt +=1
    if cnt: result += str(snt)
    return result
print(compress_string("aaabbbcccccca")) # a3b2c6a1 출력

정규표현식과 XML(294p~)

파이썬에서 정규표현식을 사용하려면 import re를 해야함.

주민등록번호 예외처리

1.전체 텍스트를 공백 문자로 나눈다(split)
2.나누어진 단어들이 주민등록번호 형식인지 조사한다.
3.단어가 주민등록번호 형식이라면 뒷자리를 '*'로 변환한다.
4.나누어진 단어들을 다시 조립한다.

  • 정규식 미사용
data = """
park 800905-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 800905-*******
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-*******

정규표현식 시작하기 (298p)

정규표현식의 기초 메타문자

. ^ $ * + ? {} [] \ | ()
  • 문자 클래스 []
  1. [] 안의 두 문자 사이에 하이폰(-)을 사용하게 되면 두 문자 사이의 범위(From - To)를 의미한다
    [a-c] = [abc] , [0-5] = [012345]
  1. 문자 클래스 내에서 ^ 메타 문자가 사용될 경우에는 반대(not)라는 의미를 갖는다.
    [^0-9]라는 정규 표현식은 숫자가 아닌 문자만 매치된다.
  • [a-zA-Z] : 알파벳 모두
  • [0-9] : 숫자 모두
  1. 자주 사용하는 문자 클래스
    \d : 숫자와 매치, [0-9]와 동일한 표현식이다.
    \D : 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식이다.
    \s : whitespace 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식이다. 맨 앞의 빈 칸은 공백문자(space)를 의미한다.
    \S : whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식이다.
    \w : 문자+숫자(alphanemeric)와 매치, [a-zA-Z0-9]와 동일한 표현식이다
    \W : 문자+숫자(alphanemeric)가 아닌 문자와 매치, [^a-zA-Z0-9]와 동일한 표현식이다

4.Dot(.)

  • 정규표현식의 Dot(.) 메타 문자는 줄바꿈 문자인 \n를 제외한 모든 문자와 매치됨을 의미한다.
a.b        # a 와 b 사이에 줄바꿈 문자를 제외한 어떤 문자가 들어가도 모두 매치

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

a[.]b        # a 와 b 사이에 Dot(.) 문자가 있으면 매치

"a.b"라는 문자열과 매치, "a0b"라는 문자열과는 매치되지 않는다.

5.반복(*)

ca*t       #  * 문자 바로 앞에 있는 a가 0번이상 반복되면 매치 

5-1. 반복(+)

ca+t       #  + 문자 바로 앞에 있는 a가 1번이상 반복되면 매치 

5-2. 반복({m,n}, ?)
1) {m}

ca{2}t     # a가 2번 반복되면 매치

2) {m, n}

ca{2,5}t     # a가 2번~5번 반복되면 매치

3) ? / ? 메타 문자가 의미하는 것은 {0,1}이다.

ab?c      # b가 0번~1번 사용되면 매치  =  b가 있어도 되고 없어도 된다

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

import re
p = re.compile('ab*')

re.compile의 결과로 리턴되는 객체 p(컴파일 된 패턴 객체)를 이용하여 그 이후의 작업을 수행 가능

정규식을 이용한 문자열 검색(303p)

컴파일된 패턴 객체는 다음과 같은 4가지 메소드는 제공한다.

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

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

match 객체의 메소드(306p)

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

끝 인덱스의 위치는 +1해서 알려주는듯 (end()메소드의 경우 총 길이수가 나온다)

컴파일 옵션 / 정규식을 컴파일 할 때 다음과 같은 옵션을 사용할 수 있다.

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

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

컴파일 옵션 DOTALL,S (308p)

# 옵션 미사용 시 줄바꿈 \n은 포함하지않아 None값을 리턴
import re
p = re.compile('a.b')
m = p.match('a\nb')
print(m)

# 결과 >>> None
# 옵션 DOTALL 사용 시 줄바꿈 \n을 포함 가능
import re
p = re.compile('a.b', re.DOTALL)
m = p.match('a\nb')
print(m)

# 결과 >>> <_ser.SRE_Match object at 0x01FCF3D8>

컴파일 옵션 IGNORECASE, I

p = re.compile('[a-z'], re.I)   #  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>

컴파일 옵션 MULTILINE, M

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']

^ 메타 문자에 의해 python 이라는 문자열이 사용된 첫번째 라인만 매치가 된 것이다.
하지만 ^ 메타 문자를 문자열 전체의 처음이 아니라 각 라인의 처음으로 인식시키고 싶은 경우에 re.MULTILINE 또는 re.M을 쓰면 된다.

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']

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

컴파일 옵션 VERBOSE, X

charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')
charref = re.compilr(r"""
&[#]		    #Start of a numeric entity reference
(
    0[0-7]+	    #Octal form
    |[0-9]+	    #Decimal form
    |x[0-9a-fA-F]+       #Hexadecimal form
)
;		    #Trailin semicolon
""", re.VERBOSE)

백슬래시 문제(312p)

"\section" 이라는 문자열을 찾기위한 정규식을 만든다 할 때
\s 가 whitespace로 해석되어 매치가 이상하게 된다.

\section

은 아래와 동일한 의미이다.

[\t\n\r\f\v]ection        # \s 문자가 이스케이프 코드 \t,\n,\r,\f,\v로 해석됨

의도한대로 매칭을 하고 싶다면 다음과 같이 변경해야 한다.

\\section

즉, 위 정규식에서 사용한 \ 문자가 문자열 그 자체임을 알려주기 위해 \ 2개를 사용하여 이스케이프 처리를 해야하는 것이다.

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

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

Raw String(313p)

정규식 엔진에 \ 문자 2개를 전달하려면 아래처럼 백슬래시 4개를 써야한다.

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

그래서 파이썬 정규식에는 Raw String이라는 규칙이 생겨났다.
컴파일 해야하는 정규식이 Raw String임을 알려주는 문법이다.

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

위와 같이 정규식 문자열 앞에 r 문자를 삽입하면 이 정규식은 Raw String 규칙에 의하여
백슬래시 2개 대신 1개만 써도 2개를 쓴 것과 동일한 의미를 갖게 된다.

profile
김죵입니당 ^^

0개의 댓글