68
Regualar expression ( 정규표현식 ) 김선영 sunyzero@gmail(dot)com 전: 2016-10-13 가메 출판사 http://www.kame.co.kr 인사이트 http://blog.insightbook.co.kr 저자블로그 http://sunyzero.tistory.com

정규표현식 Regular expression (regex)

Embed Size (px)

Citation preview

Page 1: 정규표현식 Regular expression (regex)

Regualar expression (정규표현식)

김선영

sunyzero@gmail(dot)com

버 전: 2016-10-13가메 출판사 http://www.kame.co.kr

인사이트 http://blog.insightbook.co.kr

저자블로그 http://sunyzero.tistory.com

Page 2: 정규표현식 Regular expression (regex)

Preface

Regular Expression (정규표현식)의약칭 REGEX(리젝스,레젝스)

혹은 RE라고표현하기도한다.

string pattern은문자열의조합되는규칙

meta charater는 다른의미를수식하는문자

grep은정규식을평가할수있는유틸리티입니다.

egrep, fgrep은 grep의특화된버전입니다.

sed는스트림에디터입니다.

awk는패턴식을다룰수있는언어툴입니다.

Page 3: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

H. Hangul

Page 4: 정규표현식 Regular expression (regex)

String, pattern

문자열중에는일정한규칙이존재하는경우가있다.

e-mail 주소의경우 :

중간에 @ 문자가 등장

@ 문자의 오른쪽은 dot 와영문, 아스키코드로이루어짐; 왼쪽은계정명

Web URL의경우 :

http:// 으로시작

호스트이름뒤에는 URI 가붙고디렉토리구조로 명명

CGI 기법이 사용될 경우에 ? 이등장할수도 있음

IPv4 주소의경우 :

111.222.111.222 의 4개의 숫자로이루어져있다.

Page 5: 정규표현식 Regular expression (regex)

REGEX의예시

요상해보이지만배우고나면별것아니다.

몇시간이면 다배울수있는간단한 것들이다.

a.cdef?

[a-zA-Z]+

.*boy

(caret|dollar)

\(.*/\)[^/]*

^Do.*\?$

http://\([a-zA-Z0-9.-]\)/.*

https?://.*\?(.*)

REGEX를 배운 뒤에 해석해봅시다!

Page 6: 정규표현식 Regular expression (regex)

REGEX : POSIX, PCRE

REGEX에는여러변종이있지만가장유명한것은아래 2가지:

POSIX REGEX

UNIX 계열표준정규표현식

PCRE (Perl Compatible Regular Expression)

Perl 정규표현식호환으로확장된 기능을가지고있다.

Page 7: 정규표현식 Regular expression (regex)

REGEX : POSIX REGEX

POSIX REGEX

UNIX 계열표준정규표현식

POSIX 표준

BRE (Basic RE), ERE (Extended RE)가있다.

기능도적은데꼭 POSIX REGEX를배워야하나?

POSIX REGEX부터배워야다른변종 REGEX를접할때혼란을줄일수있다.

Page 8: 정규표현식 Regular expression (regex)

REGEX : POSIX RE : BRE, ERE

POSIX REGEX에서제공되는 2가지기법

BRE : Basic REGEX

grep이작동되는 기본값

ERE : Extended REGEX

좀더 많은표현식과 편의성을제공한다.

다음에나올 meta character중에 ERE라고적혀있는것을 의미한다.

egrep의기본값이다.

POSIX ERE를 기준으로배워두는게초반에는혼동을줄일수있다.

Page 9: 정규표현식 Regular expression (regex)

REGEX : PCRE

Perl Compatible Regular Expression

Perl에서제공되던 REGEX의기능이매우훌륭하여...

이를 다른언어에서도제공하기 위해 만들어진 기능

C언어기반으로 시작

POSIX REGEX에 비해좀더성능이좋다.

현재는 PCRE2 버전을사용

과거 PCRE에서사용되던 pcregrep은 pcre2grep으로 버전업

알아두면도움이된다.

하지만 부담스럽다면 조금나중에배워도된다.

Page 10: 정규표현식 Regular expression (regex)

REGEX and EBNF

REGEX와 EBNF 문법

특히 *, +, ?, [...]는 EBNF의영향이크다.

EBNF를포멀한형태로패턴화

즉 EBNF를알고있다면학습이쉬워진다.

* EBNF (Extended Backus-Naur Form)

Page 11: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 12: 정규표현식 Regular expression (regex)

REGEX : command line utility

grep (global regular expression print)

유닉스에서 가장 기본적인 REGEX 평가유틸리티

sed

stream editor로서 REGEX 기능을일부탑재하고있다.

awk

REGEX뿐만 아니라문자열관련의방대한기능을가진프로그래밍언어

제일 많은기능을가지고 있다.

awk를만든 사람이 누군지알아두는 것도좋다.

grep >>> sed >>> awk 순으로공부를하는편이좋다.

여기서는 지면상 가장기초적인 grep, egrep을중점적으로 살펴보겠다.(아주 가끔 sed, awk의일부 기능을 소개하겠지만... 그냥 넘어가도무방하다)

Page 13: 정규표현식 Regular expression (regex)

grep : matcher selection

grep 실행시 matcher를고를수있다.

-G

BRE를 사용하여 작동한다. (기본값)

-E

ERE를 사용하여작동한다. egrep으로 작동시킨것과같다.

-P

PCRE를사용하여 작동한다. pcre2grep으로작동시킨것과 같다.

-F

고정길이 문자열을 탐색하는모드로 작동한다. 실상은 fgrep과같다.

장점 :속도가빠르다.

Page 14: 정규표현식 Regular expression (regex)

grep : options

grep 주요옵션

--color

Surround the matched (non-empty) strings.

-o

Print only the matched (non-empty) parts of a matching line

-e PATTERN

Use PATTERN as the pattern. This can be used to specify multiple search

patterns, or to protect a pattern beginning with a hyphen (-).

Page 15: 정규표현식 Regular expression (regex)

grep : options

grep 주요옵션

-v, --invert-match

Invert the sense of matching, to select non-matching lines.

-c

Suppress normal output; instead print a count of matching lines for each

input file.

-q, --quite

Quiet; do not write anything to standard output. Exit immediately with zero

status if any match is found, even if an error was detected.

Page 16: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 17: 정규표현식 Regular expression (regex)

POSIX REGEX: meta char.

문자 지정 . 임의의 문자 한 개를 의미합니다.

반복 지정

? 선행문자패턴이 0개 혹은 1개 나타납니다. - ERE

+ 선행문자패턴이 1개 이상 반복됩니다. - ERE

* 선행문자패턴이 0개 이상 반복됩니다.

{m,n}(interval) 반복수를 직접 지정할 수 있습니다. - EREm이나 n중에 하나를 생략할 수 있다.

(예) {3} : 3번 반복 {,7} : 7번 이하 {2,5} : 2~5번 반복

위치 지정^ 라인의 앞부분을 의미합니다.

$ 라인의 끝부분을 의미합니다.

그룹 지정[...] 안에 지정된 문자들 그룹 중에 한 문자를 지정합니다.

[^...] 안에 지정된 그룹의 문자를 제외한 나머지(여집합)를 지정합니다.

기타

\ (escape) 메타의 의미를 없애줍니다.

| (alternation,choice) OR연산을 합니다. - ERE

( ) 괄호는 패턴을 그룹화 및 백레퍼런스의 작동을 합니다. - ERE

* ERE - Extended Regular Expression

(ERE를 사용하면 약간의 속도 저하가 발생하는 플랫폼도 있으나 큰 차이는 없다.)

* POSIX RE - IEEE std 1003.1 (International standard)

Page 18: 정규표현식 Regular expression (regex)

Any single character

dot/period : . - any single character

c.b : cab, cbb, ccb, cdb, c1b, c2b 등등

a..b : axyb, a12b, ax0b, a#-b 등등

a.........b : 이런방식으로는쓰지않는다.

quantifier, interval 기법을쓰는 것이더현명하기때문이다. (바로뒷장에서살펴보자)

$ var3='abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123'

$ echo $var3 | grep --color 'c.b'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123

$ echo $var3 | grep --color 'c\.b'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123

* 예제 타이핑시 맨 앞의 $ 문자는 프롬프트이므로 타이핑하지 않는다.

* 예제는 bash shell prompt에서 실행하는 것으로 가정한다.

Page 19: 정규표현식 Regular expression (regex)

Quantifier (수량자)

?, +, *, {m,n} - 수량자의종류는총 4가지이다.

수량자는선행문자패턴(or atom이라고도함)을수식하는기능을가진다.

아래패턴의의미를생각해보자.

X?ML

can*

can+

http.*

? : question mark * : asterisk, star

+ : plus sign {}: (curly) braces

Page 20: 정규표현식 Regular expression (regex)

Quantifier (수량자)

X?ML : XML or ML

?앞에 문자인 X가 0개혹은 1개가존재한다.

can* : ca, can, cann, cannn, ...

*앞에 문자인 n이 0개이상 존재한다.

can+ : can, cann, cannn, cannnn, ...

+앞에문자인 n이 1개이상존재한다.

http.* : http://, httpd, https, http1234 ...

"http"뒤에어떤 문자도붙을수있다. 혹은붙지않을수도있다.

참고로 * 수량자만 BRE (Basic RE)이다.

당연히나머지수량자는 ERE이다.

? : question mark * : asterisk, star

+ : plus sign {}: (curly) braces

? 수량자가 수식하는 선행문자패턴은 X이다.

Page 21: 정규표현식 Regular expression (regex)

Quantifier (수량자)

{m,n} - interval expression

abc{2,5} : abcc, abccc, abcccc, abccccc

interval expression은몇몇유틸, RE matching engine에서는지원않는다.

e.g. awk (gawk는 --re-interval옵션으로 interval expression을켤수 있다)

{n} {n,} {n,m}은표준이고, {,m}은 GNU extension이다.

연습 : ?, *, +를 { }으로표현하면?

{0,}는 무엇일까?

{,1}는 무엇일까?

{1,}는 무엇일까?

? : question mark * : asterisk, star

+ : plus sign {}: (curly) braces

Page 22: 정규표현식 Regular expression (regex)

EBNF vs REGEX quantifier

* (The Kleene Star) vs (The Kleene Plus)

곱셈은 0을곱하면 0이된다. = 즉 * 는 0개이상을의미한다.덧셈은 0을 더하면 1이된다. = 즉 + 는 1개이상을 의미한다.

단순하게외우기보다는 이해를 하고나면잊어버리지 않는다.

* (The Kleene Star)

= means 0 or more occurrences

C를 임의의 문자라고 할 때 :

C * 0 = NULL (C를 0을 곱하면)

C * 1 = C (C에 1을 곱하면)

C * 2 = CC (C에 2를 곱하면)

C * 3 = CCC

...

C * n = n (즉 *는 0개 이상)

+ (The Kleene Plus)

= means 1 or more occurrences

C를 임의의 문자라고 할 때 :

C + NULL = C (C에 0을 더하면)

C + "1개의 C" = CC (1개의 C를 더하면)

C + "2개의 C" = CCC (2개의 C를 더하면)

C + "3개의 C" = CCCC

...

C + "n개의 C" = (즉 +는 1개 이상)

Page 23: 정규표현식 Regular expression (regex)

Quantifier (수량자) : BRE vs ERE

grep은기본값으로 BRE로작동하므로 :

* 수량자만바로사용가능

+, ?, { } 패턴은 \ (back-slash)를앞에더해줘야만한다.

egrep은기본값으로 ERE로작동하므로 :

*, +, ?, { } 패턴의모든기능이기본적으로제공된다.

egrep을사용하는모드를기본으로배워두는게좀더편리하다.

자세한차이는 back-slash를다룰때다시다루겠다.

여기서는 * 수량자만 BRE기능이라는점만숙지하고대충넘어가자.

? : question mark * : asterisk, star

+ : plus sign {}: (curly) braces

Page 24: 정규표현식 Regular expression (regex)

Anchor

^, $ - 패턴의위치를지정하는패턴이다.

^ftp : "ftp"로시작하는행

^$ : 비어있는행 (행의시작과끝에아무런문자도없다)

<BR>$ : <BR>로끝나는경우

간혹라인단위처리를하지않는경우, 즉개행문자(newline)

단위로처리하지않는경우에는 $는문서의끝을의미한다.

^ : caret

$ : dollar sign

Page 25: 정규표현식 Regular expression (regex)

Character sets

[ ], [^ ] - character class

[abcd] : a, b, c, d 중에하나

[0-9] : 0, 1, 2, ... , 9

[a-zA-Z0-9] : 대소문자알파벳과숫자

[^0-9] : [0-9]을제외한나머지

^ 문자자체를그룹에넣으려면?

^이 [ 바로뒤에만 오지않으면 된다.

[0-9^]

혹은 escape 시키거나...

[ ] : (square) brackets

Page 26: 정규표현식 Regular expression (regex)

Practice #1-a : POSIX BRE

REGEX로 단어를 검색해보자. (붉은색부분이매칭된결과)

패턴해석

p 가등장하고,

그다음에 [a-d]중에적어도 1번이상이등장하고,

그다음에 ous가등장하는경우

$ grep --color "p[abcd]\+ous" /usr/share/dict/words

opacous

opacousness

semiopacous

Page 27: 정규표현식 Regular expression (regex)

Practice #1-b : POSIX BRE

anchor를 이용해서패턴을 수정

패턴해석

p가등장하고,

그다음에 [a-d]중에적어도 1번이상이등장하고,

그다음에 ous가매칭의끝부분에등장하는경우

$가 지정되면 그뒤로는라인의끝을의미한다.

$ grep --color "p[abcd]\+ous$" /usr/share/dict/words

opacous

semiopacous

Page 28: 정규표현식 Regular expression (regex)

Practice #2

log data를 검색 (아래와 같은 로그가 있다고 가정 : 파일명 exjournal.log 으로 가정)May 09 18:02:40 dev03.rh0xhf su[43726]: (to root) sunyzero on pts/14

May 09 18:02:40 dev03.rh0xhf su[43726]: pam_systemd(su-l:session): Cannot create session

May 09 18:02:40 dev03.rh0xhf su[43726]: pam_unix(su-l:session): session opened for user root by (uid=1000)

May 10 14:07:58 dev03.rh0xhf systemd[1272]: Time has been changed

May 10 15:35:56 dev03.rh0xhf su[43726]: pam_unix(su-l:session): session closed for user root

May 20 22:40:10 dev03.rh0xhf su[31978]: pam_unix(su-l:session): session closed for user root

May 25 17:11:54 dev03.rh0xhf systemd[1272]: Time has been changed

May 30 15:51:30 dev03.rh0xhf su[63881]: (to root) sunyzero on pts/5

May 30 15:51:30 dev03.rh0xhf su[63881]: pam_systemd(su-l:session): Cannot create session

May 30 15:51:30 dev03.rh0xhf su[63881]: pam_unix(su-l:session): session opened for user root by (uid=1000)

May 30 15:54:53 dev03.rh0xhf su[63881]: pam_unix(su-l:session): session closed for user root

May 30 15:55:16 dev03.rh0xhf su[63977]: (to root) sunyzero on pts/5

May 30 15:55:16 dev03.rh0xhf su[63977]: pam_systemd(su-l:session): Cannot create session

May 30 15:55:16 dev03.rh0xhf su[63977]: pam_unix(su-l:session): session opened for user root by (uid=1000)

May 30 15:57:28 dev03.rh0xhf su[63977]: pam_unix(su-l:session): session closed for user root

pam_systemd가 session 생성에 실패한 로그만 뽑아 보고 싶다.

= pam_systemd 문자열이 들어간 행만 뽑아내야 한다.

Page 29: 정규표현식 Regular expression (regex)

Practice #2 (con't)

grep활용. (붉은색강조된부분이 매칭된결과)

$ grep --color pam_systemd exjournal.log

May 09 18:02:40 dev03.rh0xhf su[43726]: pam_systemd(su-l:session): Cannot create session

May 30 15:51:30 dev03.rh0xhf su[63881]: pam_systemd(su-l:session): Cannot create session

May 30 15:55:16 dev03.rh0xhf su[63977]: pam_systemd(su-l:session): Cannot create session

$ grep --color -A 1 "pam_systemd" exjournal.log

May 09 18:02:40 dev03.rh0xhf su[43726]: pam_systemd(su-l:session): Cannot create session

May 09 18:02:40 dev03.rh0xhf su[43726]: pam_unix(su-l:session): session opened for user root by (uid=1000)

--

May 30 15:51:30 dev03.rh0xhf su[63881]: pam_systemd(su-l:session): Cannot create session

May 30 15:51:30 dev03.rh0xhf su[63881]: pam_unix(su-l:session): session opened for user root by (uid=1000)

--

May 30 15:55:16 dev03.rh0xhf su[63977]: pam_systemd(su-l:session): Cannot create session

May 30 15:55:16 dev03.rh0xhf su[63977]: pam_unix(su-l:session): session opened for user root by (uid=1000)

패턴 매칭에서 다음 행을 뽑아주는 패턴은 없다.

이건 grep의 옵션(-A, -B)으로 해결할 문제이다.

실패한 유저명은 그 다음행의 로그에 나온다.

매칭에 성공한 행의 뒷 행을 출력하려면?

Page 30: 정규표현식 Regular expression (regex)

Tip! - grep : line control options

-A NUM, --after-context=NUM

Print NUM lines of trailing context after matching lines.

-B NUM, --before-context=NUM

Print NUM lines of leading context before matching lines.

-C NUM, -NUM, --context=NUM

Print NUM lines of output context.

e.g.) -C 1 equal to -A 1 -B 1

--group-separator=SEP

Use SEP as a group separator. By default SEP is double hyphen (--).

--no-group-separator

Use empty string as a group separator.

Page 31: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 32: 정규표현식 Regular expression (regex)

Greedy matching

greedy matching 이란?

pattern 은최대한많은수의매칭을하려고하는성질이있다.

<.+>이 <b>이아니라 <b>real ... </i>까지매칭된결과 = greedy matching

greedy matching 후 result set의범위를줄여나가면서정확한 표현식을 완성하도록해야한다.

<b>real ... </i>의 result set에서 <b>만뽑아내려면?

표현식을 더세밀하게작성하면 된다. = 뒷장에서살펴보자.

$ var2="It’s gonna be <b>real</b>It’s gonna <i>change everything</i> I feel"

$ echo $var2 | egrep -o "<.+>"

<b>real</b>It's gonna <i>change everything</i>

* 예제 타이핑시 맨 앞의 $ 문자는 프롬프트이므로 타이핑하지 않는다.

Page 33: 정규표현식 Regular expression (regex)

Greedy matching (con't)

<.+> 에서임의의문자인 . 를 [^<>] 표현으로변경하면?

$ var2="It’s gonna be <b>real</b>It’s gonna <i>change everything </i> I feel"

$ echo $var2 | egrep -o "<.+>"

<b>real</b>It's gonna <i>change everything</i>

$ echo $var2 | egrep -o "<[^<>]+>"

<b>

</b>

<i>

</i>

<.+> . [^<>]

태그 부분만 뽑아낸 결과다.

greedy matching된 결과에서 더 세밀하게 패턴을 조정했다.

Page 34: 정규표현식 Regular expression (regex)

Non-greedy matching

최소매칭기능 == greedy matching의반대개념

앞서 <.+> 대신에 [ 을사용하면최소매칭이되는데...

POSIX RE에서는 패턴을수정하여 non-greedy matching 효과와같은결과의패턴을 만든다.

POSIX RE에서는 non-greedy matching 수량자를제공하지는않는다.

따라서패턴을변경해서 non-greedy matching 결과를만드는것이다.

하지만 PCRE는 non-greedy matching을 쉽게 할수있는 quantifier를제공한다.

이를 lazy quantifier라고부른다.

<[^<>]+>

Page 35: 정규표현식 Regular expression (regex)

Non-greedy matching : lazy quantifier

Lazy quantifier (PCRE 기능)

lazy quantifier를사용하면 non-greedy matching을쉽게할수있다.

단지 quantifier에 suffix로 ?를더하면 된다.

PCRE에서만지원되므로 POSIX REGEX 모드에서는사용할 수없다.

* grep -P : PCRE matcher를 사용하도록 한다. pcre2grep을 사용해도 된다.

$ echo $var2 | grep -P -o "<.+?>"

<b>

</b>

<i>

</i>

PCRE의 Lazy quantifier를 이용해서

non-greedy matching을 간단하게 표현할 수 있다.

Page 36: 정규표현식 Regular expression (regex)

Non-greedy matching (con't)

On POSIX RE : It dosen't support non-greedy matching.

On PCRE : It can be non-greedy matching by lazy quantifier.

* 예제 타이핑시 맨 앞의 $ 문자는 프롬프트이므로 타이핑하지 않는다.

$ echo $var2 | egrep -o "<[^<>]+>"

<b>

</b>

<i>

</i>

$ echo $var2 | grep -P -o "<.+?>"

<b>

</b>

<i>

</i>

Page 37: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 38: 정규표현식 Regular expression (regex)

Back-slash

meta char.의의미를없앤다. 아래 2가지패턴의차이는?

1번패턴 : c.b

cab, cbb, ccb, cdb, c1b, c2b 등등이지만...

2번패턴 : c\.b

c.b : dot(.)가 메타의의미가아닌진짜일반문자 '.'을 의미하게된다.

$ var3='abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123'

$ echo $var3 | grep --color 'c.b'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123

$ echo $var3 | grep --color 'c\.b'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123

Page 39: 정규표현식 Regular expression (regex)

Back-slash (con't)

BRE에서 ERE의일부기능을표현할때사용한다.

예를들어 :

ERE의 {m,n}을 BRE로표현할때 \{m,n\}으로사용한다.

ERE의 ?을 BRE로 표현할때 \?으로사용한다.

?, +, { }, |, ( )에대해 back-slash를사용한다. (BRE인경우에만...)

BRE에서 back-slash를 ERE pattern으로 해석하도록하는 용도로사용하는 경우는가끔 헷갈릴수 있으므로, 왠만하면 ERE만 사용하는것이좋다.

즉 egrep을사용하는경우에는 back-slash가필요없다.

예제로살펴보자.

Page 40: 정규표현식 Regular expression (regex)

Back-slash (con't)

BRE에서 ERE의 ?, { }, +, |, ( ) 패턴사용시앞에사용.

grep은기본값으로 BRE를사용하므로위와같이 \+ 으로사용해야한다.

* 는 BRE이므로 back-slash를사용할 필요가없다.

$ echo $var3 | grep --color '[0-9bc]*'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123

$ echo $var3 | grep --color '[0-9bc]+'

매칭 실패!!! 아무것도 출력되지 않는다. (왜냐하면 +가 ERE이기 때문이다)

$ echo $var3 | grep --color '[0-9bc]\+'

abc cab cbb ccb zxy cdb c1b c2b c.b c*b 123+앞에 \를 사용해야 성공!

Page 41: 정규표현식 Regular expression (regex)

Back-slash (con't)

back-slash를문자앞에두는행동을...

escape 시킨다고표현한다.

예를 들어 \. 으로 적으면 ". 을이스케이프시켰다"고표현한다.

왜 escape 라고표현할까?

Parser의의미를생각해보면직관적으로이해할 수있을것이다.

그래도모르겠다면 숙제~~

\.

Page 42: 정규표현식 Regular expression (regex)

Practice #3 : back-slash

BRE vs ERE : 우선 BRE의 특징부터살펴보자.

$ var4='URLs : http://asdf.com/en/ , https://asdf.com/en/'

$ echo $var4 | grep --color 'http://[A-Za-z./]*'

URLs : http://asdf.com/en/ , https://asdf.com/en/

var4 변수에 URL 주소를 2개 넣었다.

그리고 grep을 이용해서 'http://[A-Za-z./]*' 패턴 적용

Page 43: 정규표현식 Regular expression (regex)

Practice #3 : back-slash

BRE vs ERE : 앞서 패턴에서 +를 추가했더니 실패한다.

해법은? ERE에서 사용되는메타 문자앞에 back-slash 추가!

$ echo $var4 | grep --color 'http://[A-Za-z./]+'

매칭 실패!!! 아무것도 출력되지 않는다. (왜냐하면 +가 ERE이기 때문이다)

$ echo $var4 | grep --color 'http://[A-Za-z./]\+'

URLs : http://asdf.com/en/ , https://asdf.com/en/

+는 ERE이므로

BRE가 기본인 grep에서는 +를 인식하지못하고 실패한다.

하지만 +앞에 back-slash를 추가해주면 성공한다.

Page 44: 정규표현식 Regular expression (regex)

Practice #3 : back-slash

BRE vs ERE :

ERE를 사용하는 egrep에서는굳이 back-slash가없어도된다.

$ echo $var4 | egrep --color 'http://[A-Za-z./]+'

URLs : http://asdf.com/en/ , https://asdf.com/en/

ERE를 사용하는 경우에는

grep -E 혹은 egrep 으로 명령한다.

Page 45: 정규표현식 Regular expression (regex)

Practice #4-a

www.naver.com 페이지에서 URL링크를추출해보자.

curl : 터미널에서웹페이지를접속하는유틸

$ curl -s http://www.naver.com | egrep -o 'http://[0-9A-Za-z.]+/'

http://www.naver.com/

http://static.naver.net/

http://www.naver.com/

http://static.naver.net/

...생략...

$ curl -s http://www.naver.com | egrep --color 'http://[0-9A-Za-z.]+/'

...생략...

ERE를 사용하는 egrep은

+앞에 back-slash를 사용하지않아도 된다.

Page 46: 정규표현식 Regular expression (regex)

Practice #4-b

www.naver.com 페이지에서 URL링크를추출해보자.

중복되는링크를제거해보자.

$ curl -s http://www.naver.com | egrep -o 'http://[0-9A-Za-z.]+/' | sort | uniq

http://blog.naver.com/

http://cafe.naver.com/

http://castbox.shopping.naver.com/

http://cecs.naver.com/

http://entertain.naver.com/

...생략...

Page 47: 정규표현식 Regular expression (regex)

Practice #4-c

www.naver.com 페이지에서 URL링크를추출해보자.

img 태그만추출해보자.

$ curl -s http://www.naver.com | egrep -o "<img [^<>]+>"

<img data-src="http://img.naver.net/static/www/dl_qr_naver.png" width="68" height="8

4" alt="네이버 앱 QR코드" />

<img data-src="http://img.naver.net/static/www/up/2012/naver_homepage.png" width="88

0" height="31" alt="시작페이지" usemap="#sliding" />

...생략...

Page 48: 정규표현식 Regular expression (regex)

Tip! BRE vs ERE

어떤 툴이 BRE를 사용하는지 ERE를 사용하는지알아두면언제 back-slash를 붙여야 하는지 쉽게 판단할 수있다.

BRE를사용하는유틸

grep (기본값), vim, sed ...

ERE를 사용하는유틸

egrep, awk

PCRE는 별개의문제지만 기본적으로 ERE를 베이스로 한다.

Page 49: 정규표현식 Regular expression (regex)

Practice #4-d

www.naver.com 페이지에서 URL링크를추출해보자.

아래 ERE를 BRE로바꿔보자 (egrep대신에 grep을 사용하도록 한다.)

$ curl -s http://www.naver.com | egrep -o "<img [^<>]+>"

$ curl -s http://www.naver.com | egrep -o 'http://[0-9A-Za-z.]+/' | sort | uniq

$ curl -s http://www.naver.com | grep -o "<img [^<>]\+>"

$ curl -s http://www.naver.com | grep -o 'http://[0-9A-Za-z.]\+/' | sort | uniq

BRE를 사용할 때는 어디에 back-slash를

추가해야하는지 기억해두자.

Page 50: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 51: 정규표현식 Regular expression (regex)

( ) : Back-reference, subst. , alternation

( ) 괄호는여러가지기능으로사용된다.

back-reference

group

alternation 기능에도 group 기능을사용한다.

Page 52: 정규표현식 Regular expression (regex)

Back-reference

매칭된결과를다시사용하는패턴 (백레퍼런스)

"( )"로묶인패턴매칭부분을 "\#"의형태로재사용(#는숫자가순서대로), 0번은전체매칭결과

options

-v : invert

--color : Surround the matched (non-empty) strings

$ egrep "^(.+):x:[0-9]+:[0-9]+:.*:/home/\1:" /etc/passwd

sunyzero:x:500:500:Steven Kim:/home/sunyzero:/bin/bash

linuxer:x:502:502::/home/linuxer:/bin/bash

$ egrep -v "^(.+):x:[0-9]+:[0-9]+:.*:/home/\1:" /etc/passwd

... (생략, 상상하시기 바랍니다) ...

( ) : parenthesis

Page 53: 정규표현식 Regular expression (regex)

Back-reference (con’t)

back-reference 응용 : tag로감싸여진부분추출

$ var2='It’s gonna be <b>real</b>It’s gonna <i>change everything</i> I feel'

$ echo $var2 | egrep -o '<([a-zA-Z0-9]+)>.*</\1>'

<b>real</b>

<i>change everything</i>

$ echo $var2 | egrep --color '<([a-zA-Z0-9]+)>.*</\1>'

... 생략 ...

Page 54: 정규표현식 Regular expression (regex)

Alternation

( )는 alternation 용도로도사용됨

"( )" alternation 이나 pattern group을묶을때도사용된다.

묶을때사용했어도 back-reference의기능도함께가진다.

$ echo "cat is not dog" | egrep -o "(cat|dog)"

cat

dog

$ echo "My Childhood~~~ bye bye" | egrep -o "(child|boy)?hood"

hood

Page 55: 정규표현식 Regular expression (regex)

Practice #4-e

www.naver.com 페이지에서 URL링크를추출해보자.

<a ...> ... </a> 로감싸진태그내용을추출해보자.

(a|A) 부분이 back-reference가되고첫번째소괄호이므로 \1 이된다.

(a|A) : a 혹은 A가등장하는 경우

$ curl -s http://www.naver.com | egrep -o "<(a|A) [^<>]+>.+</\1>"

<a href="http://www.navercorp.com/" target="_blank" id="plc.intronhn">회사소개</a>

<a href="http://mktg.naver.com/" id="plc.adinfo">광고</a>

<a href="https://help.naver.com/" id="plc.helpcenter">네이버 고객센터</a>

<a href="https://submit.naver.com/" id="plc.search">마이비즈니스</a>

...생략...

egrep이므로 ERE를 사용하고있는데,

grep의 BRE로 바꿔서 사용하려면?

Page 56: 정규표현식 Regular expression (regex)

Practice #4-e (con't)

grep의 BRE로 변경해보면?

BRE에서는 ERE meta character인 ?, +, { }, ( ) , | 를 escape 시켜야한다.

$ curl -s http://www.naver.com | grep -o "<\(a\|A\) [^<>]\+>.\+</\1>"

<a href="http://www.navercorp.com/" target="_blank" id="plc.intronhn">회사소개</a>

<a href="http://mktg.naver.com/" id="plc.adinfo">광고</a>

<a href="https://help.naver.com/" id="plc.helpcenter">네이버 고객센터</a>

<a href="https://submit.naver.com/" id="plc.search">마이비즈니스</a>

...생략...

Page 57: 정규표현식 Regular expression (regex)

Practice #4-f

www.naver.com 페이지에서 URL링크를추출해보자.

jpg, png 확장자를가진파일링크만추출해보자.

주의 할 점은확장자는 대문자일 수도있다. 즉 JPG, jpg 둘다잡아내야한다.

위 REGEX의 \.은 진짜 dot 문자를의미하는 것이다. (.을이스케이프 시킨것!)

$ curl -s http://www.naver.com | egrep -o 'http://[0-9A-Za-z./_]+\.(jpg|JPG|png|PNG)'

http://img.naver.net/static/www/dl_qr_naver.png

http://img.naver.net/static/www/up/2012/naver_homepage.png

http://img.naver.net/static/www/mobile/edit/2016/0609/mobile_16305721761.jpg

http://img.naver.net/static/www/mobile/edit/2016/0610/mobile_164630175157.JPG

http://img.naver.net/static/www/m/guide/dummy_1X1.jpg

...생략...

Page 58: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Alternation

E. Substitution

F. Boundary

G. Character class

Page 59: 정규표현식 Regular expression (regex)

Substitution - sed (stream ed)

sed에서제일많이쓰는기능이 substitution이다.

sed의 subst. 기능은 vim의 substitution command와같다.

sed의 substitution에서 separator는 slash(/)를많이쓰지만 comma(,)를 쓰기도한다. 기계적으로 slash만쓰는걸로외웠다면지식을 업데이트하자!

vim의 substitution command는 sed의기능이포함된것뿐이다!

= sed를알면 vim도 알고... UNIX는이렇게서로연관된기능들이많다.

sed는 BRE를기반으로하므로 \+ 로표현되었다.

$ echo $var2 | sed -e "s/<[^<>]\+>/ /g"

It's gonna be real It's gonna change everything I feel

$ echo $var2 | sed -e "s,<[^<>]\+>, ,g"

< > : chevron

Page 60: 정규표현식 Regular expression (regex)

Substitution - awk

awk에서도위의모든기능을구현할수있다.

awk의 gsub(global substitution)에서 REGEX로교체하는방법이다.

awk는 ERE를 사용하므로 + 앞에 back slash를쓰지않는다.

$ echo $var2 | awk '{ gsub(/[ ]*<[^<>]+>[ ]*/, " "); print }'

It’s gonna be real It’s gonna change everything I feel

{ } : (curly) brace

Page 61: 정규표현식 Regular expression (regex)

Practice #4-e

www.naver.com 페이지에서 URL링크를제거해보자.

<a ...> ... </a> 로감싸진태그내용을일반 메시지로변경해보자.

( ), |, + 앞에 back-slash를쓴이유는?

sed는 BRE를쓰기 때문이다.

ERE를 쓰려면 -r 옵션을사용하면된다.

$ curl -s http://www.naver.com | sed -n "s,<\(a\|A\) [^<>]\+>\(.\+\)</\1>,\2,gp"

<dd class="f">회사소개</dd>

<dd>광고</dd>

<dd>네이버 고객센터</dd>

<dd>마이비즈니스</dd>

...생략...

Page 62: 정규표현식 Regular expression (regex)

1. String patternA. REGEX 종류 : POSIX, PCRE

B. POSIX REGEX의 종류 : BRE, ERE

2. Utility : grep, sed, awk

3. POSIX REGEX 문법A. REGEX meta characters

B. Greedy Matching / Non-greedy Matching

C. Back-slash

D. Back-Reference / Substitution / Alternation

E. Boundary

F. Character class

Page 63: 정규표현식 Regular expression (regex)

Boundary - ERE

word 경계검색에사용

\b boundary가 맞는 표현식만 찾는다. (단어 경계면 검색)

\B boundary에 맞지 않는 표현식만 찾는다. (단어 경계면이 아닌 경우만 검색)

$ var5="abc? <def> 123hijklm"

$ echo $var5 | egrep -o "[a-j]+"

abc

def

hij

$ echo $var5 | egrep --color "\b[a-j]+\b"

abc? <def> 123hijklm

$ echo $var5 | egrep --color "\B[a-j]+\B"

abc? <def> 123hijklm

Page 64: 정규표현식 Regular expression (regex)

Predefined character class

클래스 설 명

[[:alnum:]] 알파벳과 숫자들의 모음

[[:alpha:]] 알파벳들 (대소문자)

[[:blank:]] Tab(\t)을 의미

[[:cntrl:]] 제어문자들을 의미

[[:digit:]] 숫자들을 의미

[[:xdigit:]] 16진수(hex)형 숫자들을 의미, 즉 0-9a-fA-F 를 포함한다.

[[:upper:]] 알파벳 대문자

[[:lower:]] 알파벳 소문자

[[:space:]] tab(\t), CR(\r), New line(\n) 을 포함한다.

[[:print:]] 출력 가능한 문자들

[[:graph:]] 공백을 제외한 문자들

[[:punct:]] 출력 가능한 특수문자들

Page 65: 정규표현식 Regular expression (regex)

Predefined character class (con't)

[...]안에조합가능

sunyzero@email까지만잘렸다. 모두나오게하려면?

$ var5="[email protected]:010-8500-80**:Sun-young Kim:AB-0105R"

$ echo $var5 | egrep -o "^[[:alpha:]@]+"

sunyzero@email

$ echo $var5 | egrep -o "[[:upper:][:digit:]-]{8}"

010-8500

AB-0105R

Page 66: 정규표현식 Regular expression (regex)

REGEX and PCRE

POSIX REGEX

간단한패턴매칭에사용된다.

패턴의복잡함이늘어나면성능저하가발생.

처음엔 POSIX REGEX부터학습해야만한다.- Standard니까!

PCRE (Perl Compatible Regular Expr.)

Perl에서파생된확장된정규표현식

매우빠른속도, 확장된표현식에...

C, C++, 기타대부분의언어가지원한다. (추가라이브러리로제공)

실무라면 PCRE를사용하는편이낫다.

다음 챕터에서배우자.

Page 67: 정규표현식 Regular expression (regex)

Practice #5

IPv4 address를 REGEX로 표현하면?

IPv4주소는각요소가 0~255 (0xff)사이의값만을가져야만한다.

두자리이상의숫자범위에대해정의하려면?

Hint : 0~63까지 표현하려면...

[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}\.[0-9]{,3}

이 표현식은 IP주소로는 틀렸다.

왜냐하면단순하게 숫자 3개만 검사하므로,

333.469.789.1 처럼 범위를 벗어나도 매칭성공된다.

(6[0-3]|[5-1][0-9]|[0-9])

Page 68: 정규표현식 Regular expression (regex)

Practice #6 : Hangul, Hanja

i18n을 만족하는 Linux는 UTF-8 한글 처리도 가능하다.

$ cat <<HEREDOC >hangul-utf8.txt

This is ascii text in UTF-8 character-set.

한글은 한국어에서 사용되는 문자이다. 여기 UTF8로 인코딩된 한글과 한자(漢字)가 보이는가?

HEREDOC

$ egrep --color '한.' hangul-utf8.txt

한글은 한국어에서 사용되는 문자이다. 여기 UTF8로 인코딩된 한글과 한자(漢字)가 보이는가?

$ egrep --color '한[글자]' hangul-utf8.txt

한글은 한국어에서 사용되는 문자이다. 여기 UTF8로 인코딩된 한글과 한자(漢字)가 보이는가?

$ egrep --color '..字' hangul-utf8.txt

한글은 한국어에서 사용되는 문자이다. 여기 UTF8로 인코딩된 한글과 한자(漢字)가 보이는가?

* 첫번째 cat 명령은 redirection의 HERE document기법이다.