정규식 개론

글쓴이 Engineer Myoa 날짜

1. 정규식이 무엇인가

 

흔히 개발자 사이에서 파싱을 주제로 대화한다면 정규식에 대한 언급이 빠질리가 없습니다.

정규식은 문자열을 핸들링하는데에 있어 매우 유연하고 간결하게 표현할 수 있어 그 자체가 하나의 스니펫처럼 사용될 수 있는 강력한 언어(표현식)입니다.

파싱 뿐 아니라 단순 검색 및 치환 문자열 분리 등 매우 자주 사용됩니다.

 

정규식(正規式)은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. 정규 표현식은 많은 텍스트 편집기와 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있으며, … (중략)

컴퓨터 과학의 정규 언어로부터 유래하였으나 구현체에 따라서 정규 언어보다 더 넓은 언어를 표현할 수 있는 경우도 … (생략)

출처 : https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D

위키피디아에서 발췌한 내용에도 나와있듯이 정규식은 문자열을 핸들링하는데에 매우 강력한 힘을 지니고 있습니다.

 

아마 정규식이라는 단어뿐 아니라 코드를 많이 다뤄본 경험이 있다면

re, regular expression을 줄인 regex, regexp 등으로 명명한 변수들도 종종 보셨을 겁니다.

대다수가 raw 데이터로부터 정보를 가공하기 위함입니다.

 

정규식이 현업에서도 매우 많이 사용되고 사용될 수 밖에 없음에 대한 감이 오시나요?

 

2. 왜 개발자는 정규식을 배워야 하는가

 

결론부터 이야기하자면 배우지 않아도 상관없습니다.

그렇습니다 정규식은 어디까지나 데이터 파싱에 있어 편리함과 강력함을 가져다 줄 뿐이지,

모른다고 해서 프로그램을 생산하지 못하는것은 아닙니다.

 

하지만 배워야하는 가장 큰 이유는 바로 위에서 언급한 편리함과 강력함 입니다.

 

거창할 수 있지만 간단한 하나의 예시를 들어보겠습니다.

아래의 URL에서 호스트명만을 추출하는것을 필요로 합니다.

String URL = “https://myoaftp.duckdns.org/techlog

 

개발자의 특성과 재량에 따라 다양한 구현방법이 존재할 것입니다.

인덱스를 활용하여 필요한 정보만을 추출하는 방법과, 아닌 부분을 제거하는 방법 등 다양한 방법이 있겠으나

 

정규식이 무엇이며 왜 배워야하는지에 대한 본 글의 범주를 벗어나기 때문에 조금 더 간단한 인덱스 파싱을 이용하는 방법을 보여드릴게요.

 

 

1) 인덱스 파싱

 

url은 http:// 혹은 https://로 시작하기 때문에 “//”를 시작 인덱스로 찾습니다.

python의 find와 유사한 함수를 이용하면되겠네요. ( 언어에 따라 charAt, indexOf 등이 존재합니다)

URL.find(“//”); # returned 6.

 

호스트명의 시작위치를 찾았으니 마지막위치도 찾아야겠죠.

url은 WEB 서버의 설정에 따라서 호스트명의 마지막이 ‘/’로 끝날수도, ‘/’없이 끝날수도있습니다.

어떻게 해야할까요?

일단 뒤에서부터 ‘/’가 나올때까지 찾으면 되겠습니다.

URL.rfind(“/”) # returned 27.

즉, URL[(6+2):27]의 문자열을 추출하면됩니다. # +2는 //의 길이

 

하지만 URL이 “https://myoaftp.duckdns.org/techlog” 대신

https://myoaftp.duckdns.org” 라면?

 

다음과 같은 결과를 초래할 것입니다.

v .rfind(“/”) # returned 7.

https://myoaftp.duckdns.org

^ .find(“//”) # returned 6.

 

결국 이런 예외적 경우를 위해 다음과 같은 분기점검을 이용하여 제어해줘야 합니다.

if(lastIndexOfSlash – firstIndexOfSlash <= 1):

lastIndexOfSlash = len(URL) – 1

 

거창하게 썻지만 최종 코드는 아래와 같을 수 있겠네요.

 

    1 firstIndexOfSlash = URL.find(“//”)

    2 lastIndexOfSlash = URL.rfind(“/”)

    3 if( lastIndexOfSlash – firstIndexOfSlash <= 1):

    4 lastIndexOfSlash = len(URL) – 1

    5 

    6 if( firstIndexOfSlash != –1 ):

    7 extractHostName = URL[firstIndexOfSlash+2 : lastIndexOfSlash]

 

변수명이 길어 더 복잡해 보이기는 하지만, 생각보다 짧은 라인으로 구현하였습니다.

하지만 코드가 조금 난해하네요.

이 루틴에 대한 주석이 없다면 처음보는 사람은 이해하는데 시간을 들일 수 있습니다.

 

 

2) 정규식 사용

 

대부분의 언어에서는 정규식 사용을 위해 라이브러리를 사용해야 합니다.

 

    1 import re # regular expression 라이브러리 임포트

    2 regexResultSet = re.findall(r“https:\/\/(.*)(?:\/.*|\/)”, URL)

 

끝났습니다.

물론 findall로 찾았으니 regexResultSet은 배열의 형태를 하고 있습니다.

하지만 필요한 문자열을 먼저 찾은 후 배열요소에 접근하는 것은 정말 간단해서 문제가 되지 않습니다.

 

이처럼 아주 간단한 문법으로 아주 강력한 문자열 핸들링을 할 수 있다면

배우지 않을 이유가 있을까요?

 

 

3. 배움을 위한 조건

 

항상 그렇듯 배움에는 노력이 필요합니다.

그렇지만 노력이 여타 언어를 배우는 것만큼 필요하지는 않습니다.

 

자주 사용되는 러닝커브로 표현하자면

정도로 훈련할 있다고 봅니다.

 

강의에서는

1) 먼저 문법을 익힌

2) 다양한 테스트와 실무환경에 적용해보며

3) 정규식 챌린지 혹은 문제를 풀어보면서

학습을 진행할 것입니다.

 

잠깐씩 짬내어 잘만 배워둔다면 무궁무진한 실무활용도와 시간을 절약할 수 있습니다.

익숙해진다면 간단한 정규식 정도는 머리보다 손이 더 빠를 수도 있겠네요.


3개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다