Point_Sec_0320
파이썬 마지막 간단한 예제, 정규표현식, xml 본문
파이썬 간단한예제, 정규표현식
* 간단한 예제
- 내가 과연 프로그램을 만들 수 있을까? 물음에서 시작해보자
- 자신이 무슨 진로를 선택했는지 필자는 모르지만 우선 초기에는 다른 사람들이 만든 프로그램 파일을 분석해보는 것이 좋다
* 구구단 예제
- 1. GuGu라는 함수에 2를 입력값으로 주면 결과값을 변수에 넣는다
- 2. 당연히 결과는 리스트로 나오고 2를 넣었으니 2단이 나와야 한다
- 3. 그런 다음 일단 GuGu라는 함수를 만들고 안은 비어보자
- 4. 중요한 점은, 코드를 짜는 방식은 매우 다양하다. 자신이 처음 접하는 것이라면, 당연히 주먹구구식, 스파게티 식의 코드가 나온다. 하지만 이렇게 만드는 것부터 시작해야된다 (잘 만들어진 코드부터 만든다? 그건 베낀 것)
- 5. 그 다음, 더 좋은 방식이 있는지 고려해본다 ( 처음엔 찾을 수 없다)
# 구구단예제
* 하위 디렉터리 검색하기
- 한가지만 더 해보도록 하자
- 1. 우선 sub_dir_search.py를 작성한다. 그 안에는 search라는 함수를 작성하고 인수값은 시작 디렉터리를 입력받도록 만든다
- 2. 현재 디렉터리에 있는 파일들을 검색할 수 있도록 만들어 본다( os.listdir을 이용하면 해당 디렉터리에 있는 파일들의 리스트를 구할 수 있다.)
- 3. 그 후에 C:/ 디렉터리에 있는 파일들 중에 .py(파이썬파일)만 출력하도록 수정 ( os.path.splitext 함수를 사용하여 파일명을 확장자를 기준으로 두 부분으로 나눔)
- 4. try,except PermissionError 문을 사용하여 os.listdir 수행 시 권한이 없는 디렉터리에 접근하더라도 오류로 종료되지 않게 해주고, os.path.isdir을 이용하여 search중에 디렉터리인지 파일인지를 구분하여 디렉터리의 경우 해당경로를 들어가 다시 search하도록 만든다. ( 이와 같이 같은 함수를 함수안에서 다시 부르는 것은 '재귀함수' 라고 한다.)
# 위의 예시는 두 가지로 짰는데, 주석 밖의 코드는 ( 설명 그대로 검사 ) 주석안의 예시는 os.walk()함수 사용
* 정규 표현식
- 복잡한 문자열을 처리할 때 사용하는 기법
- 파이썬을 잘 다룰 수 있는 무기라 생각하면 된다
# 주민등록번호 뒷자리 바꾸기 예제
* 주민등록번호를 정규표현식을 쓰지 않고 바꾼 예제
- 위의 data=""" ... """ 밑을 다음 2줄로 바꾸면 똑같은 결과가 나온다
>>> pat= re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******",data))
- 뒤에 나올 그루핑을 이용한 것인데 뒤에 상세히 나온다
* 문자 클래스 []
- [abc] : 이 표현식의 의미는 ' a,b,c ' 중에 한 개의 문자와 매치를 의미
- 하이픈(-)을 사용하면 범위를 나타낸다. ( [abc] = [a-c] )
- 만약 범위나 숫자,문자 앞에 not(^)을 붙이면 '그 글자를 제외하고' 라는 의미
* Dot(.)
- 줄바꿈 문자 (\n)을 제외하고 모든 문자와 매치됨을 의미
* 반복(*)
- * 앞에있는 문자가 0부터 무한까지 반복될 수 있음을 의미
* 반복(+)
- + 앞에 있는 문자가 1부터 무한까지 반복될 수 있음을 의미
* 반복({m,n},?)
- {m} : 반드시 m앞의 수가 m번 반복
- {m,n} : 반드시 앞의 수가 m부터 n까지 사이의 횟수만큼 반복
- ? : {0,1}을 의미, 앞의 문자가 있거나 없거나를 의미
* 자주 사용하는 문자 클래스
- \d : 숫자와 매치
- \D : 숫자가 아닌 것과 매치
- \s : whitespace와 매치
- \S : whitespace가 아닌 것들과 매치
- \w : 문자 + 숫자 와 매치
- \W : 문자 + 숫자가 아닌 것들과 매치
* re 모듈( 정규표현식 제공 )
- import re
- p = re.compile(...) : 기본 형태, ...은 문자열 , re.compile의 결과로 리턴되는 객체 p를 이용, 그 이후의 작업을 수행하는데 사용된다
- match()
문자열의 처음부터 정규식과 매치되는지 조사
- search()
문자열 전체를 검색, 정규식과 매치되는지
- findall()
정규식과 매치되는 모든 문자열을 리스트로 리턴
- finditer()
정규식과 매치되는 모든 문자열을 반복가능한 객체로 리턴
# 정규표현식 예제
* match 객체의 메소드
- group() : 매치된 문자열을 리턴
- start() : 매치된 문자열의 시작 위치 리턴
- end() : 매치된 문자열의 끝 위치 리턴
- span() : 매치된 문자열의 (시작, 끝) 튜플을 리턴
# 만약 search메서드를 사용한다면 match의 start메서드와 search의 start메서드는 다른 값이 나올 수 있다
# 정규표현식 예제2
* 컴파일 옵션
- DOTALL, S : .메타 문자는 줄바꿈을 제외하지만 re.DOTALL ,re.S 옵션을 사용하면 줄바꿈 문자도 포함가능하다.
- IGNORECASE, I : 대/소문자 구별없이 매치를 수행하고자 할 때 사용한다
- MULTILINE, M : ^(문자열의 처음), $(문자열의 마지막)과 같은 메타문자가 문자열에 포함되어있을 때 같이 사용
첫 라인에만 국한되는 것이 아니라 각 라인에 모든 매칭을 적용
- VERBOSE, X : 정규식 전문가들의 정규식은 거의 암호같아 보이는 경우가 많다
이를 뜯어봐서 보기쉽게 나눠놓는다
# 컴파일 옵션 예제
* 백슬래쉬 문제
- 정규 표현식에서 혼란을 주는 요소
- \를 포함한 문자열을 찾기위한 정규식을 만들 때
- \section = [\t\n\r\f\v]ection과 같은 의미
- 첫 번째 고려사항 : "\\section"으로 하면 되지 않을까?
결론부터 , 안된다 그 이유는 리터럴 규칙에 의해 백슬래쉬 2개가 \가 되기 때문이다.
- 결국, "\\\\section"을 써야된다
- 해결 방법 : Raw String규칙을 쓸 수 있다
p= re.compile(r'\\section') -> (r'\\...')을 쓰면 된다
# 백슬래쉬 문제
* 메타문자
- | : or을 의미
- ^ : 맨처음을 의미
- $ : 맨 마지막을 의미
- & : and를 의미
- \A : ^와 같은 의미지만, re.MULTILINE과 사용해도 전체문자열의 제일 처음하고만 매치
- \Z : $와 같은 의미지만, re.MULTILINE과 사용해도 전체문자열의 제일 마지막하고만 매치
- \b : 단어 구분자, re.compile(r'\bclass\b') 이라고 하면 whitespace로 구분된 class라는 단어와 매치됨을 의미
\b만 쓸경우 backspace라는 의미의 파이썬 리터럴 규칙이 있으므로, r''형태의 Raw string과 같이 써야된다
ex) no class at all(매치) declassified, subclass (None이라는 결과가 나옴)
- \B : \b와 반대의 경우다. class주위에 whitespace가 있어서는 안된다
* 그루핑
- 그룹을 만들어 주는 메타문자는 ()이다.
- 매치된 문자열 중에서 특정부분의 문자열을 뽑아내기 위한 경우
- group(0) 매치된 전체 문자열, group(1) 첫 번째 그룹에 해당하는 문자열, group(n) n번째 그룹에 해당하는 문자열,
- 그룹이 중첩되어 있는 경우, 바깥쪽에서 안쪽으로 들어갈 경우 인덱스가 증가한다
- 그룹핑된 문자열을 "재참조"가 가능하다
ex) re.compile(r'(\b\w+)\s+\1') -> 앞의 첫번째 그룹인 (\b\w+)을 \1이 다시 참조한것
- 그루핑된 문자열에 이름 붙이기
숫자로만 그룹을 만들기에 너무 많은 양의 그룹이 나올 때 , 필요한 그룹을 가져다 쓰고 활용을 편하게 하기 위해서 많이 사용
() 맨 처음에 ?P<그룹이름>을 붙임 , (?P<name>...)
# 그루핑 예제
* 전방 탐색
- 입문자가 전방 탐색 확장 구문이 너무 암호 같아서 헷갈려하는 경우가 많다
- 긍정형 전방 탐색 : (?=...) -> ...에 해당되는 정규식과 매치되어야 하며 조건이 통과되어도 문자열이 소모되지 않음
- 부정형 전방 탐색 : (?!...) -> ...에 해당되는 정규식과 매치되지 않아야 하며 문자열 소모는 없다
* 문자열 바꾸기
- sub 메소드를 이용하여 정규식과 매치되는 부분을 변경 , 첫번째 인수는 바꿀 문자열, 두번째는 바뀐 후의 문자열
- subn은 튜플로 리턴되는데, ( 첫번째, 두번째 ) 에서 첫번째는 변경된 문자열, 두번째는 바뀐 횟수
- sub 메소드의 첫번째 인수인 바꿀 문자열에 참조 구문('\g<그룹명>') 을 써도 된다
- sub 메소드의 첫번째 인수에 함수를 넣어도 가능
* Greedy VS Non-Greedy
- (*)은 탐욕스럽기 때문에 최대한의 문자열을 다 가져오고, 탐욕을 막기 위해 (?)를 같이 써주면 억제가 된다
# 전방탐색, 문자열바꾸기, greedy&non-greedy 예제
다른 고수님들의 피드백은 필자에게 매~우 감사한 일입니다. 댓글로 피드백, 질문 모두 받겠습니다. 감사합니다.
'python' 카테고리의 다른 글
파이썬 클래스,모듈,패키지,내/외장함수 (0) | 2017.04.05 |
---|---|
파이썬_ 제어문,함수,입출력 (0) | 2017.04.04 |
리스트,튜플,딕셔너리,집합,참거짓,변수 (0) | 2017.04.03 |
파이썬이란 무엇인가?, 파이썬의 기초,자료형 (0) | 2017.04.03 |