반응형

06-2 3과 5의 배수 구하기

입력 

출력

result = 0
for n in range(1,1000):
    if n % 3 == 0 or n % 5 == 0:
        result += n
print(result)

 

06-3 게시판 페이징하기 

함수 이름

입력 

출력

def getTotalPage(m,n):
    if m % n ==0:
        return m // n 
    else:
        return m // n +1

print(getTotalPage(5,10))
print(getTotalPage(15,10))
print(getTotalPage(25,10))
print(getTotalPage(30,10))

06-4 간단한 메모장 만들기

필요한 기능?

입력 ?

출력 ?

import sys
option = sys.argv[1]

if option == '-a':
    memo = sys.argv[2]
    f = open('memo.txt','a')
    f.write(memo)
    f.write('\n')
    f.close()
elif option == '-v':
    f = open('memo.txt')
    memo = f.read()
    f.close()
    print(memo)

 

06-5 탭을 4개의 공백으로 바꾸기

import sys
src = sys.argv[1]
dst = sys.argv[2]
print(src)
print(dst)

f = open(src)
tab_content = f.read()
f.close()

space_content = tab_content.replace("\t"," "*4)
print(space_content)

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

 

06-6 하위 디렉터리 검색하기 

import os

def search(dirname):
    filenames = os.listdir(dirname)
    for filename in filenames:
        full_filename = os.path.join(dirname, filename)
        print(full_filename)
        
search("C:/")

 

특정 파일 만 출력하기

import os

def search(dirname):
    filenames = os.listdir(dirname)
    for filename in filenames:
        full_filename = os.path.join(dirname, filename)
        ext = os.path.splitext(full_filename)[-1]
        if ext == '.json':
            print(full_filename)
        
search("C:/")

하위 디렉터리 내용 출력

import os

def search(dirname):
    try:
        filenames = os.listdir(dirname)
        for filename in filenames:
            full_filename = os.path.join(dirname, filename)
            if os.path.isdir(full_filename):
                search(full_filename)
            else:
                ext = os.path.splitext(full_filename)[-1]
                if ext == '.py':
                    print(full_filename)
    except PermissionError:
        pass
    
search("C:/")

 

하위 디렉터리 검색을 쉽게 해주는 os.walk

import os

for (path, dir, files) in os.walk("C:/"):
    for filename in files:
        ext = os.path.splitext(filename)[-1]
        if ext == ".py":
            print("%s/%s" % (path, filename))

07. 정규 표현식

07-1 정규 표현식 살펴보기

복잡한 문자열을 처리 할 때 사용하는 기법으로 , 파이썬 만의 고유 문법이 아니라 문자열을 처리하는 모든 곳에서 사용한다.

 

정규 표현식은 왜 필요한가 ?

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))

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

 

07-2 정규 표현식 시작하기

.^$*+?{}[]|()

 

문자 클래스 []

[] 사이의 문자들과 매치

Dot(.) 메타 문자는 줄바꿈 문자인 \n을 제외한 모든 문자와 매치됨을 의미한다.

반복 (*) 0부터 무한대로 반복 될수 있다는 의미

반복 (+) 최소 1번 이상 반복 될 때 사용

 

반복 ({m,n}, ? )

1. {m} 

2. {m,n} 범위

3. ? {0,1}

 

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

import re

re.compile()

 

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

match()

search()

findall()

finditer()  정규식과 매치되는 문자열을 반복 가능한 객체로 돌려준다.

import re
p = re.compile('[a-z]+')

m = p.match("python")
print(m)

m = p.match("3 python")
print(m)

p = re.compile('[a-z]+')
m = p.match("python")
if m:
    print("match found:", m.group())
else:
    print('No math')

import re
p = re.compile('[a-z]+')

m = p.search("python")
print(m)

m = p.search("3 python")
print(m)

import re
p = re.compile('[a-z]+')

m = p.findall("life is too short")
print(m)

import re
p = re.compile('[a-z]+')

m = p.finditer("life is too short")
print(m)

for r in m:
    print(r)

 

match 객체의 메소드

groun()

start()

end()

span() 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려준다.

import re
p = re.compile('[a-z]+')

m = p.match("python")
print(m.group())
print(m.start())
print(m.end())
print(m.span())

import re
p = re.compile('[a-z]+')

m = p.search("3 python")
print(m.group())
print(m.start())
print(m.end())
print(m.span())

 

컴파일 옵션

DOTALL, S  : dot 문자(.) 가 줄바꿈 문자를 포함하여 모든 문자와 매치된다.

import re
p = re.compile('a.b')
m = p.match("a\nb")
print(m)

p = re.compile('a.b', re.DOTALL)
m = p.match("a\nb")
print(m)

IGNORECASET, I: 대 소문자에 관계 없이 매치한다.

import re
p = re.compile('[a-z]', re.I)
m = p.match("python")
print(m)
m = p.match("Python")
print(m)
m = p.match("PYTHON")
print(m)

 

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))

p = re.compile('^python\s\w+',re.MULTILINE)
print(p.findall(data))

VERBOSE ,X: verbose모드를 사용한다.

(정규식을 보기 편하게 만들 수도 있고 주석 등을 사용할 수도 있다.)

import re
charref = re.compile(r'&[#](-[0-7]+|[0-9]+|[0-9a-fA-F]+);')

charref = re.compile(r"""&[#] # start of a numeric entirty reference
(
-[0-7]+ #octal form
|[0-9]+ #decimal form
|[0-9a-fA-F]+ # hexadecimal form
)
; # Trailing semicolon
""", re.VERBOSE)

 

백슬래스 문제 

\ -> \\

\\ -> \\\\

07-3 강력한 정규 표현식의 세계로

메타문자

| 메타 문자는 or과 동일한 의미

import re
p = re.compile('Crow|Servo')
m = p.match('CrowHello')
print(m)

^ 메타 문자는 문자열의 맨 처음과 일치함을 의미

import re
print(re.search('^Life','Life is too short'))
print(re.search('^Life','My Life'))

$ 문자열의 끝과 매치함을 의미한다.

import re
print(re.search('short$','Life is too short'))
print(re.search('short$','Life is too short, you need python'))

\A 문자열의 처음과 매치됨을 의미한다.

^메타 문자와 동일한 의미이지만 re.MULTILINE옵션을 사용할 경우에는 다르게 해석된다.
re.MULTILINE옵션을 사용할 경우 ^은 각 줄의 문자열의 처음과 매치되지만 \A는 줄과 상관없이 전체 문자열의 처음에고만 매치된다.

 

\Z 끝과  매침

 

\b는 단어 구분자 word boundary whitespace

import re
print(re.search(r'\bclass\b','no class at all'))
print(re.search(r'\bclass\b','the declassified algotithm'))
print(re.search(r'\bclass\b','one subclass is'))

\B \b문자와 반대의 경우

import re
print(re.search(r'\Bclass\B','no class at all'))
print(re.search(r'\Bclass\B','the declassified algotithm'))
print(re.search(r'\Bclass\B','one subclass is'))

그루핑

(ABC)+

import re
m = re.search(r'(ABC)+','ABCABCABC OK?')
print(m)
print(m.group(0))

p= re.compile(r"\w+\s+\d+[-]\d+[-]\d+")
m = p.search("park 010-1234-1234")

p= re.compile(r"(\w+)\s+\d+[-]\d+[-]\d+")
m = p.search("park 010-1234-1234")
print(m.group(1))

group(0) 매치된 전체 문자열
group(1) 첫번째 그룹에 해당하는 문자열
group(2) 두번째 그룹에 해당하는 문자열
group(n) n번쨰 그룹에 해당하는 문자열
p= re.compile(r"(\w+)\s+(\d+[-]\d+[-]\d+)")
m = p.search("park 010-1234-1234")
print(m.group(2))

p= re.compile(r"(\w+)\s+((\d+)[-]\d+[-]\d+)")
m = p.search("park 010-1234-1234")
print(m.group(3))

그룹핑된 문자열 재참조하기

그룹의 또 하나 좋은 점은 한 번 그루핑한 문자열을 재참조할 수 있다는 점이다.

p = re.compile(r'(\b\w+)\s+\1')
print(p.search('Paris in the the spring').group())

그루핑된 문자열에 이름 붙이기

?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)

import re
p= re.compile(r"(?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)")
m = p.search("park 010-1234-1234")
print(m.group("name"))

import re
p= re.compile(r"(?P<word>\b\w+)\s+(?P=word)")
print(p.search('Paris in the the spring').group())

전방 탐색

import re
p= re.compile(r".+.:")
m = p.search("http://google.com")
print(m.group())

(?=...) 긍정형 전방 탐색 ..에 해당하는 정규식과 매치되어야 하며 조건이 통과되어도 문자열이 소비되지 않는다.

(?!...) 부정형 전방 탐색 .. 에 해당하는 정규식과 매치되지 않아야 하며 조건이 통과되어도 문자열이 소비되지 않는다.

import re
p= re.compile(r".+(?=:)")
m = p.search("http://google.com")
print(m.group())

.*[.].*$  파일 이름+.+확장자

.*[.][^b].*$ bat인 파일은 제외해야 한다.

.*[.]([^b]..|.[^a].|..[^t])$

.*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$

 

부정형 전방 탐색

.*[.](?!bat$).*$

.*[.](?!bat$|exe$).*$

 

문자열 바꾸기

import re
p= re.compile(r"(blue|white|red)")
m = p.sub('colour','blue socks and red shoes')
print(m)

m = p.sub('colour','blue socks and red shoes',count=1)
print(m)

m = p.subn('colour','blue socks and red shoes')
print(m)

sub메서드를 사용할 때 참조 구문 사용하기

import re
p= re.compile(r"(?P<name>\w+)\s+(?P<phone>(\d+)[-]\d+[-]\d+)")
print(p.sub("\g<phone> \g<name>","park 010-1234-1234"))

import re
p= re.compile(r"(?P<name>\w+)\s+(?P<phone>(\d+)[-]\d+[-]\d+)")
print(p.sub("\g<2> \g<1>","park 010-1234-1234"))

 

sub메소드의 매개변수로 함수 넣기

import re

def hexrepl(match):
    value = int(match.group())
    return hex(value)

p= re.compile(r"\d+")
p.sub(hexrepl,'Call 65490 for printing, 49152 for user code.')

Greedy vs Non-Greedy

import re
#greedy
s = '<html><head><title>Title</title>'
print(len(s))

print(re.match('<.*>',s).span())
print(re.match('<.*>',s).group())

#non-greedy
print(re.match('.*?>',s).group())

non-greedy문자인 ?는 *?,+?,??,{m,n}?와 같이 사용할 수 있다.

반응형

+ Recent posts