
지난 포스트 정규식 맛보기를 보고 직접 해보셨나요?
실무 능력(한국에서는 ‘짬’이라고 표현합니다)은 방법을 이해한다고 생기지 않는 것 같습니다.
1번 해보고, 2번 실패하고, 3번 막히면서 경험치가 쌓이는 거겠죠.
이번에는 실무에서 바로 사용하는 정규식 예제를 몇 개 해봅시다.
정규식은 패턴에서 시작하고, 패턴으로 끝납니다.
패턴을 정해진 문법으로 표현하는 게 정규식이죠.
실전 정규식
형식 맞추기 (Formating)
우선 쉬운 연습을 해봅시다.
회사에서 주소록을 만드느라 모든 직원에게 성명과 휴대전화번호를 받았습니다.
파일을 열어보니 전화번호의 형식이 제각각이네요.
사람이 볼 때는 상관없지만 내 안에 숨어있던 편집증이 발동합니다.
네. 형식을 통일하고 싶죠.
010-1234-5678
01023456789
010.3475.9865
010 9958 4645
- 첫 번째 형식으로 맞춰봅시다.
- 사이사이의 형태는 다르지만
숫자 3자리+숫자 4자리+숫자 4자리라는 패턴은 같습니다. - 그렇다면 한번 해봅시다.
- 찾기 :
(\d{3}).*?(\d{4}).*?(\d{4}) - 바꾸기 :
$1-$2-$3
- 찾기 :
- 그럼 이렇게 나옵니다.
010-1234-5678
010-2345-6789
010-3475-9865
010-9958-4645
- 정규식에서
(........)은 묶음을 의미합니다. 묶음은 크게 2가지로 사용합니다.(서울|대전|대구|부산)처럼 해당 부분에 여러 가지 문자가 올 수 있다는 묶음- 그리고 전화번호 예시처럼 바꿀 때 묶음에 해당하는 문자를 재활용할 때
- 문자를 재활용할 때 바꾸기 정규식에서는
$1처럼 몇 번째 묶음인지 표기합니다.
- 정규식에서
(........)묶음을$1처럼 바꾸는 걸 ‘정규식 치환’이라고 합니다. - 실무에서는 이 정규식 치환만 알아도 엄청난 시간을 단축할 수 있습니다.
- 그럼 마저 설명을 해볼게요.
\d는 숫자 1글자를 뜻합니다.- 그럼 숫자 3글자는 어떻게 쓸까요? 네,
\d\d\d처럼 쓰면 됩니다. - 숫자 10글자를
\d\d\d...쓰려면 귀찮으니까 자릿수를\d{10}처럼 적습니다. - 결국
\d{3}은 숫자 3자리,\d{4}는 숫자 4자리를 뜻하는 게 되죠. - 이걸 묶음 기호인 괄호로 묶으면
(\d{3})처럼 되고, 바꾸기에 재활용할 수 있게 됩니다.
- 그럼 숫자 3글자는 어떻게 쓸까요? 네,
.*?부분을 하나하나 뜯어봅시다..마침표는 1글자를 뜻합니다.-,a,9같은 글자는 물론 공백까지도 포함해서 아무거나 1글자입니다.*별표는 ‘직전의 글자가 있거나 없거나’라는 뜻입니다..*은 ‘아무거나 1글자가 있거나 없거나’라는 뜻이 되죠.?물음표는 가장 짧은 패턴으로 찾겠다는 걸 뜻합니다..*?는 ‘아무거나 1글자가 있거나 없거나 직후에 오는 패턴 전까지 찾겠다’라는 뜻이 되죠.
- 바꾸기에서
$1은 찾기 정규식의 첫 번째 묶음인 3자리의 숫자,$2는 두 번째 묶음인 4자리의 숫자,$3은 세 번째 묶음인 4자리의 숫자를 뜻합니다.- 묶음 사이에 있는
-는 숫자 묶음 사이에 어떤 문자로 표시할지 내가 좋아하는 기호를 넣습니다. - 바꾸기 정규식을
$1/$2/$3처럼 넣으면 결과가 ‘010/1234/5678’처럼 나오겠죠? - 묶음 위치를 바꿀 수도 있고, 한 묶음을 여러 번 써도 상관없습니다.
- 묶음 사이에 있는
- 말이 나온 김에 묶음 위치를 바꾸거나 여러 번 쓰는 예제를 하나 해봅시다.
정규식 치환
한국 사람들은 누구나 아는 광개토대왕의 연호는 ‘영락(永樂) 12년’처럼 씁니다.
한글과 한자를 나눠서 ‘영락 12년(永樂 12년)‘처럼 바꾸려면 어떻게 해야 할까요?
위에서 나왔던 묶음을 사용하면 수천 개의 단어를 패턴으로 한꺼번에 바꿀 수 있습니다.
현실의 데이터는 통일되지 않은 게 당연합니다. 아래처럼요.
영락(永樂) 12년
장수왕(長壽王)9년
의자왕(義慈王) 3
- 자, 한번 해봅시다.
- 찾기 :
([가-힣]+?)\((.+?)\)[ ]*(\d{1,2})[년]* - 바꾸기 :
$1 $3년\($2 $3년\)
- 찾기 :
- 그럼 이렇게 바뀝니다.
영락 12년(永樂 12년)
장수왕 9년(長壽王 9년)
의자왕 3년(義慈王 3년)
- 정규식을 하나하나 뜯어봅시다.
[가-힣]에서[]는 1글자를 표시하는 기호였었죠?가-힣은 한글가부터힣까지의 범위를 뜻합니다.[가-힣]은 현대 한글 전체를 모두 포함하는 범위인 1글자가 되겠죠.- 영어 소문자 전체는
a-z, 대문자 전체는A-Z, 숫자 전체는0-9처럼 범위로 표현할 수 있습니다. - 한글이나 영어 1글자를 찾으려면
[가-힣|a-z|A-Z]라고 표현하시면 됩니다. ([가-힣]+?)에서 양쪽 괄호는 묶음을 표시하는 기호이고,+는 1개 이상이라는 뜻이며,?는 최소한이라는 뜻입니다. 종합하면 한글 1글자 이상이면서 다음에 나오는 정규식 이전까지를 찾는다는 뜻이 됩니다.
- 영어 소문자 전체는
\(와\)에서\기호는 ‘이스케이프’라는 특수한 용도입니다./슬래시와는 방향이 다른 기호지요.- 묶음이라는 뜻으로 괄호인
(....)를 사용하기 때문에 실제 텍스트의 괄호를 표시하기 위한 방법입니다. (....)나+,?처럼 정규식에서 사용하는 기호는 정규식 약속 기호로 사용하기 때문에 ‘이건 정규식 기호가 아니라 그냥 문자를 표시하는 거야’라는 뜻으로 이스케이프인\기호를 앞에 붙여줍니다.
- 묶음이라는 뜻으로 괄호인
(.+?)는 아무거나 1글자 이상이면서 다음에 나오는 정규식 이전까지는 찾는 묶음입니다.[ ]*는 공백 1글자가 있거나 없거나 라는 뜻이죠.(\d{1,2})는 묶음이고 1자리나 2자리 숫자라는 뜻이 되겠죠.[년]*은 ‘년’이라는 1글자가 있거나 없거나라는 뜻이 됩니다.- 바꾸기 정규식에서
$1 $3년\($2 $3년\)를 뜯어봅시다.$1은 1번째 묶음,$2는 2번째 묶음,$3은 3번째 묶음이었죠?\(와\)는 괄호를 실제 텍스트로 표현하는 거고요.영락(永樂) 12년예시에서$1은영락,$2는永樂,$3은12묶음을 가져와서$1 $3년\($2 $3년\)로 바꾸니까영락 12년(永樂 12년)으로 치환되었습니다.- 웹사이트에서 괄호 부분을 윗첨자로 표현하고 싶다고 하면 바꾸기 정규식을 이렇게 바꾸면 될 것 같습니다.
$1 $3년<sup>$2 $3년</sup>
팁 : 수정 전후 글자 비교 (Diff)
정규식에 조금씩 재미가 느껴지시나요?
손이 빠른 당신은 이렇게 생각할 수도 있을 겁니다.
200개 정도는 내가 손으로 수정하는 게 더 빨라.
하지만 2가지 문제가 있어요.
하나는 실무할 때는 대부분 200개보다 훨씬 많은 걸 수정할 일이 생각보다 자주 생긴다는 거고,
다른 하나는 사람은 생각보다 실수를 많이 한다는 겁니다. (네, 제가 그렇습니다.)
그래서 정규식으로 치환을 하면 한 번에 실수 없이 바꿀 수 있습니다.
그리고 정규식 치환을 할 때 샘플로 검토한 부분은 내 생각대로 정확히 바뀌었지만
문서 마지막 부분이나 미처 확인하지 못한 부분에서 틀리게 바뀌는 경우가 많습니다.
그래서 원본과 수정본을 비교하여 실수를 최소화해야 합니다.
원본과 수정본을 비교하는 걸 짧게 줄여서 ‘디프(diff)‘라고 부릅니다.
온라인 툴이 많이 있으니 원본 텍스트와 수정 텍스트를 비교하는 습관을 들이면 좋습니다.
온라인 툴 말고 설치형 프로그램으로는 멜드(Meld)를 추천합니다. 멜드 사용법은 나중에 별도의 포스트로 올려보겠습니다.