본문 바로가기
  • (개인)정보보호/최신ICT 정보 공유 블로그
나의 서재/08. 손에 잡히는 정규 표현식

손에 잡히는 정규 표현식

by 노벰버맨 2021. 4. 10.

업무에 갑자기 필요해서 몇권의 책을 구매해서 읽어보니

일단 쉽고 간단하게 설명이 되어 있어서 빨리 읽을 수 있고

읽은 내용을 테스트를 통해 이해할 수 있어서 참 좋았던 것 같습니다.

정규표현식에 대해서 빠른 이해에 도움이 많이 되는 것 같습니다.

 

========================================================================================

 

1장. 정규 표현식 소개
>정규 표현식은 텍스트를 찾고 조작하는데 쓰는 문자열이다.
>정규 표현식은 일치하는 텍스트를 찾거나(검색수행), 텍스트를 찾은 뒤에 그것을 원하는 텍스트로 치환한다.(치환수행)
>정규 표현식은 mini language이다.

 

2장. 문자 하나 찾기
>문자 찾기
   - Ben : Ben이라는 문자를 찾는다.
   - 대부분의 정규표현식 엔진은 처음 일치한 텍스트만 반환한다.
   - 대소문자 구별한다.
 . ben은 일치하지 않는 문자이다.
 . 대소문자 구별을 무시하고 검색하는 별도 플래그가 있다.
 . Javascript사용자들은 i플래그를 대소문자 구별을 무시할 수 있다.
>모든 문자 찾기
   - 마침표(.) : 문자, 알파벳, 숫자, 문장부호 등과 일치하는 문자를 찾는다.
>특수 문자 찾기
   - 마침표(.)을 찾으려면 역슬래시(\)와 같이 사용해야 한다. (\.와 같이 사용하면 된다.)
   - 역슬레시(\)는 메타문자이다.
   - 역슬레시(\)를 찾으려면 \\으로 쓰면 된다.

 

3장. 문자 집합으로 찾기
>여러 문자 중 하나 일치시키기
   - 메타문자인 [ ]을 사용한다.
   - [ ]에 포함된 문자 하나를 찾는다.
   - [ns] : n이나 s를 찾는다.
>문자 집합 범위 사용하기
   - 하이픈(-) : 문자 범위를 지정할 수 있다.
   - 하이픈(-)은 []안에서만 메타문자이다. 집합 밖에서는 일반 문자로 취급한다.
   - [0-9] : 0~9 사이 중 한 문자를 찾는다. [0123456789]와 동일한 의미이다.
   - [0-9a-zA-Z] : 0~9, a~z, A~Z 중 하나를 찾는다.
>제외하고 찾기
   - ^ : ^뒤에 오는 문자를 제외한 문자를 찾는다.
   - [^0-9] : 0~9를 제외한 문자를 찾는다.

 

4장. 메타 문자 사용하기
>메타문자는 스스로 특별한 의미를 갖기 때문에 자기 자신을 문자 그대로 표현할 수 없다.
>이스케이프(\) 살표보기
   - 특별한 의미 대신 문자 자체를 뜻하기 위해 이스케이프해야 한다.
   - [를 찾으려면 \[, ]를 찾으려면 \]
>공백 문자 찾기
   - 공백 문자는 [\b], \f, \n, \r, \t, \v가 있다.
 . [\b] : 역스페이스
 . \f : 페이지 넘김
 . \n : 줄바꿈
 . \r : 캐리지 리턴
 . \t : 탭
 . \v : 수직 탭
   - 공백 문자 중 줄바꿈은 Windows에서는 \r\n, Linux, Mac에서는 \n
>특정한 문자형태와 일치시키기
   - 문자 클래스 : 자주 쓰는 문자 집합들은 특수한 메타 문자로 대신
   - 숫자와 숫자가 아닌 문자
 . \d : 숫자 하나 [0-9]와 동일
 . \D : 숫자를 제외한 나머지 [^0-9]와 동일
   - 영숫자와 영숫자가 아닌 문자
 . \w : [0-9a-zA-Z]
 . \W : [^0-9a-zA-Z]
   - 공백 문자와 공백이 아닌 문자
 . \s : 모든 공백 문자 [\f\n\r\t\v], 역스페이스 메타 문자는 제외
 . \S : 공백 문자가 아닌 모든 문자 [^\f\n\r\t\v], 역스페이스 메타 문자는 제외
   - 16진수나 8진수
 . 16진수 값 앞에 \x를 붙인다.
 . \x0A : \n과 같은 기능이다.
 . 8진수 값 앞에 \0를 붙인다.
 . \011 : \t과 같은 기능이다.
>포직스 문자 클래스
   - 메타문자와 여러 문자 조합을 줄여쓰는 방법이다.
   - posix 문자 클래스([:xdigit:] 등)는 JavaScript에서 지원하지 않는다.
   - posix 문자 클래스는 [:로 시작해서 :]로 끝난다.
 . [:alnum:] : 모든 영숫자. [a-zA-Z0-9]
 . [:alpha:] : 모든 영문자. [A-Za-z]
 . [:cntrl:] : 아스키 제어문자(아스키 0번부터 31번, 127번)
 . [:blank:] : 빈칸이나 탭문자. [\t ]와 같다.
 . [:digit:] : 한자리 숫자. [0-9]와 같다.
 . [:graph:] : [:print:]와 동일하나 공백문자는 제외한 문자
 . [:lower:] : 모든 소문자. [a-z]
 . [:upper:] : 모든 대문자. [A-Z]
 . [:print:] : 출력가능한 모든 문자
 . [:punct:] : [:alnum:]이나 [:cntrl:]가 포함되지 않은 모든 문자
 . [:space:] : 빈칸을 포함한 모든 공백문자. [\f\n\r\t\v ]와 같다.
 . [:xdigit:] : 모든 16진수 [a-fA-F0-9]와 같다.

 

5장. 반복 찾기
>문자 하나 이상 찾기
   - 문자나 집합에 속한 요소를 하나 이상 찾으려면 더하기(+)를 붙인다.
   - 문자 집합에 적용할때는 집합 바깥쪽에 써야 한다. [0-9]+
   - 메일 주소 찾기 패턴 : [\w.]+@[\w.]+\.\w+
   - 마침표(.)나 더하기(+)는 메타문자이나 집합 구성원일때는 문자그대로 취급한다.
   - 매타 문자를 문자로 취급하기 위해서 이스케이프를 사용한다.
 . +와 일치하려면 \+로 써야 한다.
>문자가 없거나 하나 이상 연속하는 문자
   - 별표(*) : 없거나 하나 이상 일치시키기. 사용은 + 와 동일
   - 메일 주소 찾기 패턴 : \w+[\w.]*@[\w.]+\.\w+
   - 예문
 <B>AK</B>and<B>HI</B>
   - 패턴 <[Bb]>.*</[Bb]>
   - 결과
 <B>AK</B>and<B>HI</B>
>문자가 없거나 하나인 문자 찾기
   - 물음표(?) : 없거나 하나 일치시키기
   - URL 찾기 패턴 : https?://[\w./]+
   - 탐지 결과 :
 http://www.abc.com
 https://www.abc.com
   - [\r]?\n[\r]?\n
 . 유닉스나 리눅스 환경에서는 \r은 제외하고 \n만 사용하기 때문에 \n 앞에 \r이 있을 경우에만 일치시키기 위한 패턴
 . [\r]과 같이 메타문자 하나가 포함된 집합을 정의하여 혼란을 방지한다.
>구간 지정하기
   - 구간은 중괄호({}) 안에 표시한다.
   - 정확한 구간 찾기
 . 구간을 이용하면 특정 개수, 최소 일치 개수, 최대 일치 개수로 일치시킬 수 있다.
 . {4} : 4개와 일치하는 경우. 찾을 문자 다음에 쓴다.
 . \w{4} : 4개 문자 찾기
   - 범위 구간 찾기
 . {2,4} : 최소 2개 최대 4개 범위에 일치시키기
 . {,4} : 최대 4개 이하 일치시키기
   - 최소값 구간 찾기
 . {2,} : 최소 2개 이상 일치시키기
 . 더히기(+) 는 {1,} 과 동일한 기능이다.
 . ?는 {,1} 또는 {0,1} 과 동일한 기능이다.
>과하게 일치하는 상황 방지하기
   - 기본적으로 *, +, {n,}는 탐욕적 수량자(가능한 한 가장 큰 덩어리 찾기)이다.
   - 게으른 수량자(문자 최소 일치)는 *?, +?, {n,}? 로 쓴다.
   - 예문
 <B>AK</B>and <B>HI</B>
   - 패턴 <[Bb]>.*?</[Bb]>
   - 결과
 <B>AK</B>
 <B>HI</B>

 

6장. 위치 찾기
>단어 경계 지정하기
   - \b는 단어의 시작이나 마지막을 일치시키고자 할때
 . 예문
 The cat scattered his food all over the room.
 . 패턴
 \bcat\b
 . 결과
 cat 단어를 찾는다. scattered는 못찾는다
   - \B : \b의 반대
 . \Bcat\B : cat이 아닌 scattered를 찾는다.
   - \bcap : cap으로 시작하는 모든 단어
   - cap\b : cap으로 끝나는 모든 단어
   - \<는 단어의 시작을 지정하고, \>는 단어의 끝을 지정한다.
>문자열 경계 지정하기
   - 문자열 전체의 시작이나 마지막 부분과 패턴을 일치시키고자 할때
   - 캐럿(^) : 문자열의 시작
   - 달러($) : 문자열의 마지막
   - ^는 대괄호 []문자 바로 다음에 쓰면 부정을 뜻하고 집합 밖에서 패턴의 시작에 사용하면 문자열의 시작을 뜻한다.
 . 예문
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 . 패턴
 ^\s*<\?xml.*\?>
 . 결과
  <?xml version="1.0" encoding="ISO-8859-1"?>
   - $ 기호도 유사한 방법으로 사용한다.
 . 패턴
 </[Hh][Ht][Mm][Ll]>\s*$
>다중행 모드 사용하기
   - (m?)은 항상 패턴 제일 앞에 두어야 한다.
   - 다중행 모드일 경우,
 . 캐릿(^)은 문자열의 시작이나 줄바꿈 다음(새로운 행)에 나오는 문자열의 시작과 일치한다.
 . 달러($)는 문자열의 마지막이나 줄바꿈 다음에 나오는 문자열의 마지막과 일치한다.
 . 시작는 각 줄의 시작이 ^이고 $가 마지막이다.
 . 예문
<script type="text/javascript">
// This will write a header:
document.write("<h1>This is a header</h1>");
// This will write two paragraphs:
document.write("<p>This is a paragraph</p>");  // 여기서 부터는 주석으로 처리된다.
document.write("<p>This is another paragraph</p>");
</script>
 . 패턴
 (?m)^\s*//.*$
 . 결과
// This will write a header:
// This will write two paragraphs:
   - 다중행 모드가 아닐 경우,
 . 전체 텍스트의 시작이 ^이고 $가 마지막이다.
 . 위의 동일한 예문에서
 . 패턴
 ^\s*//.*$
 . 결과
// This will write a header:
   - JavaScript에서는 정규표현식 literal 뒤에 m를 붙인다.

 

7장. 하위표현식 사용하기
>물음표(?), 별표(*), {2} 같은 반복 메타 문자는 자기 바로 앞에 있는 문자나 메타 문자에 적용한다.
>하위 표현식으로 묶기
   - 큰 표현식 안에 속한 일부 표현식을 한 항목으로 다루는데 한데 묶는다.
   - 하위 표현식은 괄호 사이에 사용한다.
 . 예문
The browser won't recognize more than 1 space. I know at first this might all seem pretty stupid for it to be this way, but really, it's better like this. It gives you absolute&nbsp;&nbsp;control over the document's appearance.
 . 패턴
 &nbsp;{2,}
 . 일치
 &nbsp; &nbsp;
   - IP 주소 찾기 패턴
 (\d{1,3}\.){3}\d{1,3}
   - 어떤 사용자들은 가독성을 높이고자 표현식 일부를 하위표현식으로 묶기도 하는데, 이는 사용하는 정규 표현식 구현에 따라 성능 문제가 발생할 수도 있다.
>중첩된 하위 표현식
   - 하위 표현식을 중첩해 쓰기도 한다.
   - 하위 표현식은 다른 하위 표현식을 중첩하고 그 하위 표현식은 또 다른 하위 표현식을 중첩하기도 한다.
   - OR( | ) 연산자
   - 묶음 안에서 하나를 일치시키고자 할 때
>IP주소를 구성하는 각 숫자 묶음을 유효한 조합으로 정의하는 규칙
   - 모든 한 자리 혹은 두 자리 숫자
   - 1로 시작하는 모든 세자리 숫자
   - 2로 시작하면서 두 번째 자리 숫자가 0부터 4사이의 모든 세 자리 숫자
   - 25로 시작하면서 세 번째 자리 숫자가 0부터 5사이의 모든 세 자리 숫자
   - 패턴
 (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))


8장. 역참조 사용하기
>예문
<body>
<h1>Headings</h1>
<h2>are</h2>
<h3>great</h3>
<h4>for</h4>
<h5>titles</h5>
<h6>and subtitles</h6>
</body>
>패턴
   - <[hH]1>.*</[hK]1>
>결과
   - <h1>Headings</h1>

>패턴
   - <[hH][1-6]>.*?</[hK[1-6]]1>
>결과
   - <h1>Headings</h1>
   - <h2>are</h2>
   - <h3>great</h3>
   - <h4>for</h4>
   - <h5>titles</h5>
   - <h6>and subtitles</h6>

>예문
<body>
<h1>Headings</h1>
<h2>are</h2>
<h2>great</h3>
</body>
>문장에 패턴 패턴 <[hH][1-6]>.*?</[hK[1-6]]>을 적용하면
>결과
   - <h1>Headings</h1>
   - <h2>are</h2>
   - <h2>great</h3>과 일치된다.
   - 하지만 <h2>great</h3>은 잘못된 문장이다.
   - 두번째 태그가 일치할 때 첫번째 태그가 어떤 텍스트인지 알 수 있는 정보가 없다.

>역참조로 찾기
   - 역참조는 정규 표현식 패턴으로, 앞서 일치한 부분을 다시 가리킨다.
   - 역참조를 변수와 비슷하게 생각해도 된다.
   - 예문
There is is a nifty little code that means "space" to to the browser
   - 패턴
 [ ]+(\w)[ ]+\1
   - 결과
 is is
 to to
   - [ ]+는 공백이 하나 이상 연속되는 경우 일치하고, \w+는 영숫자 문자가 하나 이상 연속되는 경우 일치하며, [ ]+는 그 뒤에 공백이 있을 때 일치한다.
   - 여기서, \1은 앞서 일치한 하위 표현식을 참조함을 의미한다. 따라서, (\w+)와 일치하는 문자는 \1과도 일치한다.
   - 자바스크립트는 역참조를 표시할 떄 역슬래시(\)를 사용하는데, 펄은 달러기호($)를 사용한다.
   - 역참조는 참조하는 표현식이 하위 표현식일 때만 동작한다.
   - 많은 구현에서 0번째 참조라고 하면 표현식 전체를 가리킨다.
 . 예문
<body>
<h1>Headings</h1>
<h2>are</h2>
<h2>great</h3>
</body>
 . 문장에 패턴 패턴 <[hH][1-6]>.*?</[hK[1-6]]\1>을 적용하면
 . 결과
 <h1>Headings</h1>
 <h2>are</h2>
>치환 작업 수행하기
   - 정규표현식을 써 치환하는 작업은 역참조와 함께 사용했을 떄 진가를 발휘한다.
   - 예문
 ben@forta.com
   - 패턴
 (\w+[\w\.]*@[\w\.]+\.\w+)
   - 치환
 <A HREF="$1</A'>mailto:$1">$1</A>
   - 치환 작업을 할 때는 정규 표현식이 두개 필요하다.
 . 원하는 부분을 일치시키는 패턴
 . 일치한 부분을 치환할때 사용하는 패턴
   - 텍스트 형식을 바꿔야 할 때 해당 텍스트를 여러 조각의 하위 표현식으로 작게 나누는 편이 유용하다.
   - 대소문자 변환하기
 . 대소문자 변환 메타 문자
 . 메타 문자 설명
\E  \L 혹은 \U 변환의 끝을 나타낸다.
\l  다음에 오는 글자를 소문자로 변환한다.
\L  \E를 만날 때까지 모든 문자를 소문자로 변환한다.
\u  다음에 오는 글자를 대문자로 변환한다.
\U  \E를 만날 때까지 모든 문자를 대문자로 변환한다.
 . \l과 \u는 바꾸고 싶은 글자 앞에 두어 각각 그 글자를 소문자와 대문자로 바꾼다.
 . \L과 \U는 \E를 만날 때까지 모든 문자를 각각 소문자와 대문자로 변환한다.
 . 예문
<body>
<h1>Headings</h1>
<h2>are</h2>
<h2>great</h3>
</body>
 . 패턴
 (<[Hh1>)(.*?)(</[Hh1>)
 . 치환 : $1\U$2\E$3
 . 결과
 <h1>HEADINGS</h1>

 

9장. 전방탐색과 후방탐색
>전방탐색은 모든 주요 정규 표현식 구현에서 지원하지만, 후방탐색은 광범위하게 지원하지 않는다.
>전방탐색 - 앞으로 찾기
   - 전방탐색(lookahead)패턴은 일치 영역을 발견해도 그 값을 반환하지 않는 패턴을 말한다.
   - 전방탐색은 실제로는 하위 표현식이며, 하위 표현식과 같은 형식으로 작성한다.
   - 전방탐색 패턴의 구문은 ?=으로 시작하고 등호(=) 다음에 일치하는 텍스트가 오는 하위 표현식이다.
 . 예문
 http://www.abc.com
 https://mail.abc.com
 ftp://ftp.abc.com
 패턴
 .+(?\:)
 . 결과
 http
 https
 ftp
   - ?= 정규 표현식 엔진에게 콜론(:)을 찾되 콜론(:) 앞에 있는 문자를 찾으라고(소비는 하지 말고) 지시한다.
   - 일부 정규표현식 문서에서는 일치하는 영역을 반환하는 동작을 표현할 때 '소비한다(consume)'라는 용어를 쓴다.
   - 모든 하위 표현식 앞쪽에 단순히 ?=를 붙이기만 하면 전방탐색 표현으로 바꿀 수 있다.
   - 하나의 검색 패턴 속에서 여러 개의 전방탐색 표현식을 사용할 수 있고, 또한 그 표현식은 패턴 안에서 어느 위치에서든 사용할 수 있다.
>후방탐색 - 뒤로 찾기
   - 후방탐색 연산은 ?<=이다.
 . 예문
 1: $600.4
 2: $10.25
 3: $47.33
 4: $112.34
 . 패턴
 (?<=\$)[0-9.]+
 . 결과
 600.4
 10.25
 47.33
 112.34
   - 전방탐색 패턴은 마침표(.)와 더하기(+)를 포함하여 텍스트의 길이를 다양하게 일치시킬 수 있으며, 매우 동적이다.
   - 반대로 후방탬색 패턴은 보통 일치시킬 텍스트의 길이를 고정해야 한다.
   - 거의 모든 정규 표현식 구현에는 이런 제약이 있다.

>부정형 전후방탐색
   - 후방탐색과 전방탐색은 반환할 텍스트의 위치 즉 찾고자 하는 부분의 앞뒤를 특별히 지정하고 싶을 때 주로 사용한다.
   - 이를 주로 긍정형 전방탐색, 긍정형 후방탐색이라 한다.
   - 부정형(negative) 전후방탐색은 비교적 덜 쓰는 방법이다.
   - 부정형 전방탐색은 앞쪽에서 지정한 패턴과 일치하지 않는 텍스트를 찾고,
   - 부정형 후방탐색도 이와 비슷하게, 뒤쪽에서 지정한 패턴과 일치하지 않는 텍스트를 찾는다.
   - 부정형을 나타낼때는 등호(=) 대신 느낌표(!)를 사용한다.
>전후방탐색 명령
   - 종류  설명
(?=)  긍정형 전방탐색
(?!)  부정형 전방탐색
(?<=)  긍정형 후방탐색
(?<!)  부정형 후방탐색
 
10장. 조건 달기
>모든 정규 표현식 구현에서 조건 처리를 지원하지는 않는다.
>정규 표현식 조건은 물음표(?)를 사용해 정의한다.
>조건 사용하기
   - 역참조 조건
 (?(backreference)true)
   - 물음표(?)로 조건을 시작하고, 괄호 안에 역참조를 지정한 다음, 역참조가 존재하는 경우에만 평가될 표현식이 바로 뒤에 나온다.
 . 예문
<!--Nav bar-->
<TD>
<a href="/home"><img src="/images/home.gif"></a>
<img src="/images/spacer.gif">
<a href="/search"><img src="/images/search.gif"></a>
<img src="/images/spacer.gif">
<a href="/help"><img src="/images/help.gif"></a>
</TD>
 . 패턴
 (<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>(?(1)\s*</Aa]>)
 . 결과
<a href="/home"><img src="/images/home.gif"></a>
<img src="/images/spacer.gif">
<a href="/search"><img src="/images/search.gif"></a>
<img src="/images/spacer.gif">
<a href="/help"><img src="/images/help.gif"></a>
   - ?(1)은 역참조 1(<A>시작 태그)이 있을 때만 수행하라는 말이다.
   - 다른 말로, 태그<A>와 일치한다면 그 뒤의 종료 태그도 일치시키라는 뜻이다.
   - ?(1)은 역참조 1이 있는지 없는지를 검사한다. 역참조 번호를 조건에서 이스케이프 할 필요는 없다.
   - 즉, ?(1)이 맞고, ?(\1)은 잘못된 것이다. 그렇지만 후자도 동작한다.
   - (?(1)\s*</Aa]>) 패턴은 조건이 충족되었을 때만 수행된다.
   - (?(backreference)true|false)
 . 조건은 else 표현식을 써서 나타낼 수 있는데 else 표현식은 역참조가 존재하지 않을 경우만 수행되는 표현식이다.
 . 예문
 123-456-7890
 (123)456-7890
 (123)-456-7890
 (123-456-7890
 . 패턴
 (\()?\d{3}(?(1)\)|-)\d{3}-\d{4}
>전후방 탐색 조건
   - 전후방탐색 조건은 전방탐색과 후방탐색 명령이 성공했는지에 따라 표현식을 수행할지 결정한다.
   - 전후방탐색 조건은 역참조(괄호안에 넣는 숫자)가 완전히 전후방탐색 표현식으로 대체되었다는 점만 빼고는 역참조 조건과 동일하다.
 . 예문
 11111
 22222
 33333-
 44444-4444
 . 패턴
 \d{5}(?(?=-)-\d{4})
 . 결과
 11111
 22222
 44444-4444
   - 하이픈이 있다는 조건을 만족하면, -\d{4}는 그 하이픈과 이어 나오는 숫자 네 개와 일치한다.
   - 더 간단한 방법으로 비슷한 결과를 얻을 수 있기 때문에 전후방탐색 조건은 자주 사용하지 않는다.

댓글