정규식 Regular Expression 기초 1/3
http://zvon.org/comp/r/tut-Regexp.html에 기반하여 설명합니다.
정규식 테스트는 http://regexr.com 을 이용하시기 바랍니다.
여타 언어나 이론들을 배우기 위해서는 제 개인적으로 2가지 플랜이 존재합니다.
하나는 수많은 예제를 보면서 메커니즘을 이해하고 잘 정돈된 문서를 보는것과
다른 하나는 처음부터 문서를 정독하면서 마지막 장까지 나아가는 방법입니다.
콕 집어 어떤게 더 좋다 라고는 말할 수 없겠지만 정규식같이 사용되는 기호들이 생소한 경우에는 전자를 이용한 방법이 더 좋았습니다. 개인적으로도 그렇게 공부했고, 기초, 중급 강의를 진행하면서도 위에 사이트에 나와있는 예제들을 전부 풀어쓰고 후에 연산자들에 대해 기술하도록 하겠습니다.
기본적으로 식은 /“정규식표현”/g 이며 특수한 상황에서 //i //gi //gim 등에 대해 사용방법도 끝에 설명하겠습니다.
첨언으로 vim에서 /(슬래시)를 입력함으로써 //g의 형태를 사용하겠다는 의미에서 검색하는 단축키가 되겠습니다.
1.
정규식은 기본적으로 case sensitive(대소문자 구별)합니다. 그 말은 hello와 Hello가 서로 다른 식이라는 것을 의미합니다.
“Hello, world” 라는 문장에서 Hello라는 식으로 검색했을 때는 “Hello, world” 부분이 매치가 되네요. 하지만 hello라는 식으로 검색했을 때는 아무 부분도 매치가 되지 않습니다.
다시 한 번 강조하지만 정규식의 기본옵션에서는 대소문자를 구분합니다.
2.
정규식에서는 모든 문자를 패턴을 위한 문자로 인식합니다. 무슨말인고 하면 “ ” 와 “ ”는 다르고 “.” 과 “..”는 다르다는 말이죠. 공백, 탭, 개행 전부다 이스케이핑(추후 나옴)없이는 전부 단일문자로 인식합니다.
위에 케이스에서도 “Hello, world!”를 Hello, world로 검색하면 “Hello, world!”가 매치 되지만
Hello, world를 검색했을경우에는 아무것도 매치가 되지않습니다.
3.
본격적으로 정규식 기호들에 대해 나오기 시작합니다.
^과 $는 각각 문장의 첫, 끝을 의미합니다.
“사과는 사과” 라는 문장에서
^사과 로 검색 시 “사과는 사과”
사과$ 로 검색 시 “사과는 사과”
가 매치됩니다.
당연히 사과^ 와 $사과 는 컴파일 에러는 나지 않지만 실행중 논리에러가 나게되죠.
(문장에 시작앞에 다른 문자가 존재할 수 없으며, 문장에 끝뒤에 다른 문자가 존재할 수 없죠)
그냥 사과 로 검색하면 “사과는 사과”가 매치되며 파이썬 정규식 모듈에서는 이를 list의 형태로 [“사과”, “사과”]를 반환합니다.
4.
앞서 ^과 $는 각각 문장의 처음, 끝을 나타낸다고 말씀드렸습니다.
그런데 실제로 ^이나 $라는 문자가 필요할 땐 어떻게 할까요?
바로 이때 이스케이핑을 하게됩니다.
\(백슬래쉬)를 사용하려는 기호나 문자앞에 배치하면 그 기능이 이스케이핑되어(escape. 키보드의 esc가 escape) 새로운 기능으로 작동하게됩니다.
바로 \^, \$ 처럼요.
위에 예제 자체는 훌륭하나 배우는 입장에서 봤을때는 영 이해하기가 귀찮은 예제입니다.
예제를 살짝 수정해보겠습니다.
^^ 오늘도 좋은하루입니다.~^^!
이 문장에서 ^^를 찾으려면 어떻게 할까요?
\^\^로 검색하면되겠죠.
“^^ 오늘도 좋은하루입니다.~^^!” 2개가 매칭됐네요.
아무래도 우리는 앞에 ^^만 구해야 할거같습니다.
^\^\^로 검색해보겠습니다.
“^^ 오늘도 좋은하루입니다.~^^!”
정확하게 원하는 결과가 나왔습니다.
$의 경우도 같습니다. $문자 자체를 사용하려면 \$.
$라는 문장맨끝을 의미하는 기호로 사용하려면 $로 사용하시면됩니다.
만약 보기가 불편하다고 ^ \^\^ 와 같이 식을 정의하면 아무것도 검색이 되지않습니다.
이것은 마치
테스트\n 과 테스트 \n이
“테스트”
“테스트 ”처럼 둘은 엄연히 다른 문자열 리터럴을 의미하기 때문에 보기 불편하더라도 익숙해지도록 노력해야합니다.
5.
“.” 은 any character. 즉 아무개 문자를 의미합니다.
.에는 거의 대부분이 해당됩니다. 영소대문자, 숫자, 한글, 특수문자, 공백 등..
하지만 포함이 안되는 것이 있죠. 바로 new line(개행문자. 즉, 엔터로 개행한)입니다. new line을 포함해서 찾는방법은 따로 있는데 지금 설명할 타이밍이 아닌거 같습니다.
맛보기로만 보여드리자면
[\w\W] 또는 [\s\S] 등으로 정의할 수 있습니다.
Case2에서 …… (점 6개)를 검색하는데 왜 powerf까지만 검색이될까요?
이유는 ul!!!의 길이가 5개이기 때문입니다.
쉽게 풀어쓰자면 Case2에서 매치되는 그룹은
[“Regula”, “r expr”, “ession”, “s are ”, “powerf”]입니다. 전부 6글자씩인데 ul!!!는 5글자이기 때문에 식에 부합하지않습니다.
뒤에 !가 하나 더 추가된다면 매치가 되겠죠.
/……/g
Regular expressions are powerful!!!!
>>> [“Regula”, “r expr”, “ession”, “s are ”, “powerf”, “ul!!!!”]
6.
5에서 “.”역시 일반적인 문자로 사용하는게 아닌 하나의 식으로 사용했었습니다.
그렇다면 정말로 .을 찾고싶다면 어떻게 할까요?
4에서 배웠던데로 이스케이핑(escape)이 필요합니다.
그저 \. 만 해주면 되는거에요.
. 으로 검색시에는 [“O”, “.”, “K”, “.”] 총 4개가 매치되는군요.
\.로 검색시에는 [“.”, “.”] 총 2개가 매치됩니다. 우리가 원하는 결과네요.
특정문자(아무개문자)와 .을 같이 찾고싶다,
.\. 식을 사용하면됩니다.
.과 특정문자를 찾고싶다면
\.. 이 되겠죠?
7.
[ ]는 문자의 집합을 나타냅니다. [ ]안에는 문자가 들어갈수도, 문자셋(set)이 들어갈수도, against식이 들어갈수도 있습니다.
배우기전에 앞서 아래와 같은 룰이 존재하므로 익히고 넘어갑시다.
– : 문자의 범위를 의미합니다.
[ㄱ-ㅎ가-힣]은 한글전체를 의미합니다.
[a-z]는 영소문자의 범위를 의미합니다.
[A-Za-z]와 같이 영문자 전부를 포함할 수도 있으며,
[0-9]처럼 숫자만을 포함할 수도 있습니다.
[ㄱ-ㅎ가-힣0-9]처럼 여러개의 문자집합을 섞어서 사용할 수도 있습니다.
^ : 문자집합을 부정합니다. 다시말해 문자 집합내의 문자를 걸러서 매치합니다.
[^a-z]는 a부터 z까지의 범위를 검색하지않습니다.
[^ 0-9]는 0부터 9까지 그리고 공백을 검색하지 않습니다.
[^ A-Za-z0-9]와 같이 여러 집합을 섞어서 사용할 수도 있습니다.
이제 위에 식을 보면
How do you do?에서 [oyu]를 검색하면
[“o”, “o”, “y”, “o”, “u”, “o”] 만 매치가됩니다.
말 그대로 o,y,u를 하나의 문자집합으로 두고 이중에 하나라도 들어가면 매치하는거죠.
[dH]. 처럼 대소문자도 구문합니다.
[가나라][방면]
“가방안에 나비가 들어왔노라면.”
이라는 문장에서 위와 같은 식으로 검색을하면
[“가방”, “나비”, “라면”] 이 매치가 되는것이죠.
이는 가방, 가면, 나방, 나면, 라방, 라면 의 경우를 검색하는 식이 의미합니다.
8.
위에서 짚고 넘어간 것처럼 –은 문자의 범위를 지정합니다.
즉 [C-K]는 [CDEFGHIJK]와 동일하고 [2-6]은 [23456]과 동일하단 의미이죠.
9.
8과 마찬가지로 위에서 ^는 문자집합을 부정하는 식이라고 언급했습니다.
예제를 보면 [^CDghi45]는 C, D g, h, i, 4, 5를 제외하고 검색한다는 뜻입니다.
[^W-Z]처럼 범위를 부정하는 방법도 있습니다.
추후에 배우겠지만 정규식은 \s \w \S \W \d \b처럼 자주 사용되는 문자집합을 사전에 정의해두고 사용할 수 있도록 만들어져있습니다. 매우 강력한 언어죠.
2부에서 뵙겠습니다.
3개의 댓글