Top Banner
조금 깊이 들여다보는 qr/정규표현식/ Korean Perl Workshop 2012 2012. 10. 20. 박근영 @gypark [email protected] http://gypark.pe.kr/wiki/Perl
155

KPW2012 조금 깊이 들여다보는 정규표현식

Nov 11, 2014

Download

Technology

raymundo reyes

Korean Perl Workshop 2012 에서 발표한 내용입니다.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: KPW2012 조금 깊이 들여다보는 정규표현식

조금 깊이 들여다보는

qr/정규표현식/

Korean Perl Workshop 2012

2012. 10. 20.

박근영

@gypark [email protected]

http://gypark.pe.kr/wiki/Perl

Page 2: KPW2012 조금 깊이 들여다보는 정규표현식

목 차

• 흔히 겪는 오류와 실수

• Perl 5.10 이후에 도입된 정규식 문법

• 자잘한 팁들

Korean Perl Workshop 2012 2

Page 3: KPW2012 조금 깊이 들여다보는 정규표현식

이 문서의 내용과 코드는 주로…

• perlretut (regular expression tutorial) – 번역: http://gypark.pe.kr/wiki/Perl/정규표현식

• perlre

• 손에 잡히는 정규표현식

– 벤 포터, 김경수 번역, 인사이트

• 한 권으로 끝내는 정규표현식

– 잰 고이바에르츠 외, 김지원 번역, 한빛미디어

• WWW …등에서 발췌

Korean Perl Workshop 2012 3

Page 4: KPW2012 조금 깊이 들여다보는 정규표현식

흔히 겪는 오류와 실수

"어째서 일치하지 않을까요?"

"어째서 여기에 일치해 버릴까요?"

Korean Perl Workshop 2012 4

Page 5: KPW2012 조금 깊이 들여다보는 정규표현식

정규식의 어려움

• 일치해야 될 문자열에 일치하는 정규식을 만드는 것은 비교적 쉽다

Korean Perl Workshop 2012 5

Page 6: KPW2012 조금 깊이 들여다보는 정규표현식

• 일치해야 될 문자열에 일치하는 정규식을 만드는 것은 비교적 쉽다

• 일치하지 말아야 할 문자열에 일치하지 않는 정규식을 만드는 것이 어렵다

Korean Perl Workshop 2012 6

Page 7: KPW2012 조금 깊이 들여다보는 정규표현식

• 일치해야 될 문자열에 일치하는 정규식을 만드는 것은 비교적 쉽다

• 일치하지 말아야 할 문자열에 일치하지 않는 정규식을 만드는 것이 어렵다

– 경우의 수가 무한함

– 테스트하기 힘듦

– 상황에 따라 적절한 타협이 필요

Korean Perl Workshop 2012 7

Page 8: KPW2012 조금 깊이 들여다보는 정규표현식

문자열의 앞에서부터 일치

• 정규표현식 일치 검사의 첫번째 원칙

“문자열에서 가능한 한

가장 앞부분에서 일치시킨다”

Korean Perl Workshop 2012 8

Page 9: KPW2012 조금 깊이 들여다보는 정규표현식

• 간단한 예 "cats and dogs" =~ / dog | cat | bird /x;

Korean Perl Workshop 2012 9

* 코드 출처: perlretut

Page 10: KPW2012 조금 깊이 들여다보는 정규표현식

• 간단한 예 "cats and dogs" =~ / dog | cat | bird /x;

• 후보들의 순서에 무관하게, 앞에서부터 일치

Korean Perl Workshop 2012 10

Page 11: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs'

Korean Perl Workshop 2012 11

Page 12: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+"/;

Greedy quantifier

Korean Perl Workshop 2012 12

Page 13: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?"/; Non-greedy quantifier로 교체

Korean Perl Workshop 2012 13

Page 14: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?"/; 성공!

Korean Perl Workshop 2012 14

Page 15: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?" dogs/; 뒤에 조건이 추가

Korean Perl Workshop 2012 15

Page 16: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?" dogs/;

이것을 기대하지만…

Korean Perl Workshop 2012 16

우리가 원한 것

Page 17: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?" dogs/;

???

Korean Perl Workshop 2012 17

우리가 원한 것 실제로 일치하는 부분

Page 18: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/".+?" dogs/;

Non-greedy 수량자는 정규식이 일치할 때까지

문자열을 소모하며 일치부를 확장지킨다.

Korean Perl Workshop 2012 18

실제로 일치하는 부분

Page 19: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/"[^"]+" dogs/; /./ 대신에 따옴표를 제외한 문자들만 일치하도록 수정

Korean Perl Workshop 2012 19

Page 20: KPW2012 조금 깊이 들여다보는 정규표현식

• 수량자와 같이 사용할 때 '"10" cats and "20" dogs' =~ m/"[^"]+" dogs/; 성공

Korean Perl Workshop 2012 20

Page 21: KPW2012 조금 깊이 들여다보는 정규표현식

• 경계가 한 글자가 아니면…… "<b>10</b> cats and <b>20</b> dogs"

Korean Perl Workshop 2012 21

Page 22: KPW2012 조금 깊이 들여다보는 정규표현식

• 경계가 한 글자가 아니면…… "<b>10</b> cats and <b>20</b> dogs" =~ m'<b>((?!</b>).)+</b> dogs'; 부정 전방탐색

Negative Lookahead

Korean Perl Workshop 2012 22

Page 23: KPW2012 조금 깊이 들여다보는 정규표현식

같은 위치에서는 왼쪽 후보부터

"Her name is Janet." =~ / Jane | Janet /x; 이 문자열은…

Korean Perl Workshop 2012 23

* 코드 출처: perlretut

Page 24: KPW2012 조금 깊이 들여다보는 정규표현식

"Her name is Janet." =~ / Jane | Janet /x; 이 문자열은…

절대로 'Janet'에 일치하지 않을 것임

Korean Perl Workshop 2012 24

Page 25: KPW2012 조금 깊이 들여다보는 정규표현식

"Her name is Janet." =~ / Janet | Jane /x / \bJane\b | \bJanet\b /x / \bJanet?\b /x 정규식 리터럴에서는 이런 실수가 적지만, 패턴이 변수에 들어가 있으면 눈에 띄지 않음

Korean Perl Workshop 2012 25

Page 26: KPW2012 조금 깊이 들여다보는 정규표현식

실패하면 거기서 끝나지 않는다

• 일치에 실패하면, 문자열의 다음 글자부터 다시 일치를 시도함

Korean Perl Workshop 2012 26

Page 27: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; "TGA" codon의 위치를 검색

Korean Perl Workshop 2012 27

* 코드 출처: perlretut

Page 28: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /TGA/g ) { print "TGA at ", pos $dna, "\n"; } 1차 시도

Korean Perl Workshop 2012 28

Page 29: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 8 TGA at 18 TGA at 23

Korean Perl Workshop 2012 29

Page 30: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } 2차 시도

세 글자씩 끊어가며 검색

Korean Perl Workshop 2012 30

Page 31: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 TGA at 23 ???

… 어째서?

Korean Perl Workshop 2012 31

Page 32: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 마지막으로 성공한 후

Korean Perl Workshop 2012 32

Page 33: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 마지막으로 성공한 후 그 직후부터 일치를 시도하여 실패하고

Korean Perl Workshop 2012 33

Page 34: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 마지막으로 성공한 후 그 직후부터 일치를 시도하여 실패하고 그 다음 글자부터 재시도하여 실패하고

Korean Perl Workshop 2012 34

Page 35: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 마지막으로 성공한 후 그 직후부터 일치를 시도하여 실패하고 그 다음 글자부터 재시도하여 실패하고 TGA at 23 그 다음 글자부터 재시도하여 성공

Korean Perl Workshop 2012 35

Page 36: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /\G(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; }

3차 시도

/\G/ - /g flag를 사용하여 일치된 마지막 지점

Korean Perl Workshop 2012 36

Page 37: KPW2012 조금 깊이 들여다보는 정규표현식

# "ATC GTT GAA TGC AAA TGA CAT GAC" $dna = "ATCGTTGAATGCAAATGACATGAC"; while ( $dna =~ /\G(\w\w\w)*?TGA/g ) { print "TGA at ", pos $dna, "\n"; } TGA at 18 성공 앵커에 일치해야 하기 때문에, 그 다음 글자부터 진행할 수 없다

Korean Perl Workshop 2012 37

Page 38: KPW2012 조금 깊이 들여다보는 정규표현식

Korean Perl Workshop 2012 38

Page 39: KPW2012 조금 깊이 들여다보는 정규표현식

“…하지 않은 것”을 찾기

• 완전한 단어 “cat”에 일치 /\bcat\b/

Korean Perl Workshop 2012 39

Page 40: KPW2012 조금 깊이 들여다보는 정규표현식

• 완전한 단어 “cat”에 일치 /\bcat\b/ • 어딘가에 포함되어 있는 “cat”?

Korean Perl Workshop 2012 40

Page 41: KPW2012 조금 깊이 들여다보는 정규표현식

• 완전한 단어 “cat”에 일치 /\bcat\b/ • 어딘가에 포함되어 있는 “cat”?

• “cat”을 제외한 모든 단어?

Korean Perl Workshop 2012 41

Page 42: KPW2012 조금 깊이 들여다보는 정규표현식

• 완전한 단어 “cat”에 일치 /\bcat\b/ • 어딘가에 포함되어 있는 “cat”?

• “cat”을 제외한 모든 단어?

• “cat”이 포함되지 않은 단어?

Korean Perl Workshop 2012 42

Page 43: KPW2012 조금 깊이 들여다보는 정규표현식

• 어딘가에 포함되어 있는 “cat”

bobcat, category, staccato, 123cat456 …

Korean Perl Workshop 2012 43

* 코드 출처: 한 권으로 끝내는 정규표현식, 67

Page 44: KPW2012 조금 깊이 들여다보는 정규표현식

• 어딘가에 포함되어 있는 “cat”

bobcat, category, staccato, 123cat456 …

• 오답 /\Bcat\B/

Korean Perl Workshop 2012 44

Page 45: KPW2012 조금 깊이 들여다보는 정규표현식

• 어딘가에 포함되어 있는 “cat”

bobcat, category, staccato, 123cat456 …

• 오답 /\Bcat\B/

• 정답 /\Bcat|cat\B/

Korean Perl Workshop 2012 45

Page 46: KPW2012 조금 깊이 들여다보는 정규표현식

• “cat”을 제외한 모든 단어 snake, bat, dog, bobcat, …

Korean Perl Workshop 2012 46

* 코드 출처: 한 권으로 끝내는 정규표현식, 372

Page 47: KPW2012 조금 깊이 들여다보는 정규표현식

• “cat”을 제외한 모든 단어 snake, bat, dog, bobcat, …

• 흔히 보이는 오답

/\b[^cat]+\b/ – [^…]를 단어를 배제하는 용도로 쓰면 안 됨

Korean Perl Workshop 2012 47

Page 48: KPW2012 조금 깊이 들여다보는 정규표현식

• “cat”을 제외한 모든 단어 snake, bat, dog, bobcat, …

• 흔히 보이는 오답

/\b[^cat]+\b/ – [^…]를 단어를 배제하는 용도로 쓰면 안 됨

• 마찬가지

/\b[^c][^a][^t]\b/

Korean Perl Workshop 2012 48

Page 49: KPW2012 조금 깊이 들여다보는 정규표현식

• “cat”을 제외한 모든 단어 snake, bat, dog, bobcat, …

• 정답

/\b(?!cat\b)\w+/

Korean Perl Workshop 2012 49

Page 50: KPW2012 조금 깊이 들여다보는 정규표현식

• “cat”이 포함되어 있지 않은 모든 단어 snake, bat, dog, bobcat, …

/\b(?:(?!cat)\w)+\b/

Korean Perl Workshop 2012 50

* 코드 출처: 한 권으로 끝내는 정규표현식

Page 51: KPW2012 조금 깊이 들여다보는 정규표현식

“일치하지 않음” vs “아닌 것에 일치함”

$str = 'I paid $30 for 100 apples';

Korean Perl Workshop 2012 51

* 코드 출처: 손에 잡히는 정규표현식, 93

Page 52: KPW2012 조금 깊이 들여다보는 정규표현식

$str = 'I paid $30 for 100 apples'; # 가격에만 일치 $str =~ /\$\d+/;

Korean Perl Workshop 2012 52

Page 53: KPW2012 조금 깊이 들여다보는 정규표현식

$str = 'I paid $30 for 100 apples'; # '$'는 제외하고 숫자에만 일치 $str =~ /(?<=\$)\d+/; # 후방탐색

Korean Perl Workshop 2012 53

Page 54: KPW2012 조금 깊이 들여다보는 정규표현식

my $str = 'I paid $30 for 100 apples'; # 가격이 아닌 수량에만 일치?? $str =~ /(?<!\$)\d+/; # 부정형 후방탐색

Korean Perl Workshop 2012 54

Page 55: KPW2012 조금 깊이 들여다보는 정규표현식

my $str = 'I paid $30 for 100 apples'; # 가격이 아닌 수량에만 일치?? $str =~ /(?<!\$)\d+/; # 부정형 후방탐색 # 실패

Korean Perl Workshop 2012 55

Page 56: KPW2012 조금 깊이 들여다보는 정규표현식

my $str = 'I paid $30 for 100 apples'; # 가격이 아닌 수량에만 일치?? $str =~ /(?<!\$)\d+/; # 부정형 후방탐색 # 실패 $str =~ /\b(?<!\$)\d+/; # 앵커가 필요함

Korean Perl Workshop 2012 56

Page 57: KPW2012 조금 깊이 들여다보는 정규표현식

전후방탐색의 활용

(?<=before)match(?=after)

이 형태만 생각하기 쉬움

Korean Perl Workshop 2012 57

Page 58: KPW2012 조금 깊이 들여다보는 정규표현식

일련의 숫자, 그 뒤에 일련의 문자 형태

# 1a, 1ab, 123abcd, .... /^\d+[a-z]+$/

Korean Perl Workshop 2012 58

Page 59: KPW2012 조금 깊이 들여다보는 정규표현식

• 전체 문자열이 4~6 글자인 것만 /^\d{1}(?:[a-z]){3,5}$/ | /^\d{2}(?:[a-z]){2,4}$/ | /^\d{3}(?:[a-z]){1,3}$/ | /^\d{4}(?:[a-z]){1,2}$/ | /^\d{5}(?:[a-z]){1}$/ … 무리입니다

Korean Perl Workshop 2012 59

Page 60: KPW2012 조금 깊이 들여다보는 정규표현식

• 정규식 안의 Perl 코드 /^(\d++) (??{ my $d = length($1); # 숫자열의 길이에 따라 my $min = 4-$d; # 문자열의 최소 최대 길이를 $min = 1 if $min < 1;# 결정하고 my $max = 6-$d; "[a-z]{$min,$max}"; # 정규식을 구성 }) $/x; … 무리입니다

Korean Perl Workshop 2012 60

Page 61: KPW2012 조금 깊이 들여다보는 정규표현식

• 정규식과 코드의 협동

/^\d+[a-z]+$/ and length($_) >= 4 and length($_) <= 6

Korean Perl Workshop 2012 61

Page 62: KPW2012 조금 깊이 들여다보는 정규표현식

• 전방탐색

/^(?=.{4,6}$)\d+[a-z]+$/ 둘 이상의 조건을 동시에 검사

Korean Perl Workshop 2012 62

Page 63: KPW2012 조금 깊이 들여다보는 정규표현식

전방탐색과 조건식 결합

올바른 우편번호 찾기 11111 (o) 22222 (o) 33333- (x) 44444-4444 (o)

Korean Perl Workshop 2012 63

* 코드 출처: 손에 잡히는 정규표현식, 102

Page 64: KPW2012 조금 깊이 들여다보는 정규표현식

올바른 우편번호 찾기 11111 (o) 22222 (o) 33333- (x) 44444-4444 (o) /\d{5}(-\d{4})?/ 세번째 문자열을 걸러내지 못함

Korean Perl Workshop 2012 64

Page 65: KPW2012 조금 깊이 들여다보는 정규표현식

올바른 우편번호 찾기 11111 (o) 22222 (o) 33333- (x) 44444-4444 (o) /\d{5}(?(?=-)-\d{4})/ 전방탐색이 성공하면 그 뒤의 패턴도 검사

Korean Perl Workshop 2012 65

Page 66: KPW2012 조금 깊이 들여다보는 정규표현식

Case shifting

\Q \L \l \U \u \E

– Perl에서는 큰따옴표 문자열 문법의 일부

– 정규표현식 문법이 아님

Korean Perl Workshop 2012 66

Page 67: KPW2012 조금 깊이 들여다보는 정규표현식

$str1 = "\uhello"; # $str1 = 'Hello' 'Hello' =~ /$str1/; # 일치됨

Korean Perl Workshop 2012 67

Page 68: KPW2012 조금 깊이 들여다보는 정규표현식

$str1 = "\uhello"; # $str1 = 'Hello' 'Hello' =~ /$str1/; # 일치됨 $str2 = '\uhello'; # $str2 = '\uhello' 'Hello' =~ /$str2/; # 런타임 에러

“Unrecognized escape \u …”

• 사용자 입력을 받은 경우도 마찬가지

Korean Perl Workshop 2012 68

Page 69: KPW2012 조금 깊이 들여다보는 정규표현식

• 쌍따옴표 문자열 내에 적용되는 순서 – 변수 치환 – 이스케이프, 논리 캐릭터 – Case shift

$ perl -e 'print "\QP*rl\n"' P\*rl\ <- (\n 있음)

Korean Perl Workshop 2012 69

Page 70: KPW2012 조금 깊이 들여다보는 정규표현식

• 정규표현식에 적용되는 순서 – 변수 치환 – Case shift – 이스케이프, 논리 캐릭터

Korean Perl Workshop 2012 70

Page 71: KPW2012 조금 깊이 들여다보는 정규표현식

• 묘하다 "\n" =~ qr/\n/ # 일치 "\n" =~ qr/\Q\n/ # 불일치 (qr/\\n/, '\n'에 일치) "\n" =~ qr/\U\n/ # 불일치! (qr/\N/, Perl5.8 이하 에러) "\n" =~ qr/\l\n/ # 일치! "\n" =~ qr/\L\n/ # 일치!

Korean Perl Workshop 2012 71

Page 72: KPW2012 조금 깊이 들여다보는 정규표현식

• 심지어 "\Q\n" =~ qr/\Q\n/ # 불일치 "\U\n" =~ qr/\U\n/ # 불일치 "\L\n" =~ qr/\L\n/ # 일치

Korean Perl Workshop 2012 72

Page 73: KPW2012 조금 깊이 들여다보는 정규표현식

Korean Perl Workshop 2012 73

Page 74: KPW2012 조금 깊이 들여다보는 정규표현식

/x flag

$str = "abc - 123"; $str =~ /\S+ - \d+/; 아주 잘 일치함

Korean Perl Workshop 2012 74

Page 75: KPW2012 조금 깊이 들여다보는 정규표현식

$str = "abc - 123"; $str =~ / \S+ # 단어 - # 대시 \d+ # 숫자 /x;

이것은 일치하지 않는다!

Korean Perl Workshop 2012 75

Page 76: KPW2012 조금 깊이 들여다보는 정규표현식

$str = "abc - 123"; $str =~ / \S+\ # 단어,공백 -\ # 대시,공백 \d+ # 숫자 /x;

스페이스는 /[ ]/ 또는 /\ /로 바꿔야 되는 걸 잊지 말자

Korean Perl Workshop 2012 76

Page 77: KPW2012 조금 깊이 들여다보는 정규표현식

Perl 5.10 ~ Perl 5.14 에서 도입된 문법들 \N 메타캐릭터

Relative Backreferences \g{3} \g{-2}

Named Backreferences (?<year>) \g<year>

Branch Reset

PREMATCH, MATCH, POSTMATCH

Possessive Quantifier <[^>]++>, 백트래킹하지 않는 부분식

/r flag

Named Subpattern

Recursive Pattern

Korean Perl Workshop 2012 77

Page 78: KPW2012 조금 깊이 들여다보는 정규표현식

\N metacharacter

/./ 임의의 캐릭터 하나

– /s 옵션이 있을 때는 뉴라인"\n"에 일치

– 없을 때는 뉴라인에 일치하지 않음

/\N/ /s 옵션에 무관하게 항상 뉴라인을 제외한

임의의 캐릭터 하나

78 Korean Perl Workshop 2012

Page 79: KPW2012 조금 깊이 들여다보는 정규표현식

Relative backreferences

# 오동작 my $a99a = '([a-z])(\d)\g2\g1'; # a11a, g22g, ... my $line = 'code=e99e'; if ( $line =~ /^(\w+)=$a99a$/ ) { print "$1 is valid\n"; }

앞에 괄호가 추가되면서 번호가 안 맞는다

Korean Perl Workshop 2012 79

* 코드 출처: perlretut

Page 80: KPW2012 조금 깊이 들여다보는 정규표현식

# 오동작 my $a99a = '([a-z])(\d)\g2\g1'; # a11a, g22g, ... my $line = 'code=e99e'; if ( $line =~ /^(\w+)=$a99a$/ ) { print "$1 is valid\n"; } my $a99a = '([a-z])(\d)\g{-1}\g{-2}' 현재 위치 기준.

Korean Perl Workshop 2012 80

Page 81: KPW2012 조금 깊이 들여다보는 정규표현식

Named backreferences

• 매치되는 그룹에 이름을 붙임

• 앞의 예 다시 my $a99a = '(?<char>[a-z])(?<digit>\d)\g{digit}\g{char}';

Korean Perl Workshop 2012 81

Page 82: KPW2012 조금 깊이 들여다보는 정규표현식

• 그룹의 순서가 서로 다른 패턴을 일괄처리 $fmt1 = '(?<y>\d\d\d\d)-(?<m>\d\d)-(?<d>\d\d)'; $fmt2 = '(?<m>\d\d)/(?<d>\d\d)/(?<y>\d\d\d\d)'; $fmt3 = '(?<d>\d\d)\.(?<m>\d\d)\.(?<y>\d\d\d\d)'; for my $d ( qw( 2006-10-21 15.01.2007 10/31/2005 ) ) { if ( $d =~ m{$fmt1|$fmt2|$fmt3} ){ print "day=$+{d} month=$+{m} year=$+{y}\n"; } } 정규식 외부에서는 %+ 해시를 써서 접근

Korean Perl Workshop 2012 82

* 코드 출처: perlretut

Page 83: KPW2012 조금 깊이 들여다보는 정규표현식

Branch Reset

$time = '2305'; if ( $time =~ /(\d\d|\d):(\d\d)|(\d\d)(\d\d)/ ) { print "hour = $1 minute = $2\n"; # ?? print "hour = $3 minute = $4\n"; # ?? }

몇 번째 그룹에 캡처가 될 지 모름

defined 검사 필요

Korean Perl Workshop 2012 83

* 코드 출처: perlretut

Page 84: KPW2012 조금 깊이 들여다보는 정규표현식

$time = '2305 GMT'; if ( $time =~ /(?|(\d\d|\d):(\d\d)|(\d\d)(\d\d))\s+([A-Z]{3})/ ) { print "hour = $1 minute = $2 zone = $3\n"; } (?| 후보1 | 후보2 | 후보3 | … )

Korean Perl Workshop 2012 84

Page 85: KPW2012 조금 깊이 들여다보는 정규표현식

$time = '2305 GMT'; if ( $time =~ /(?|(\d\d|\d):(\d\d)|(\d\d)(\d\d))\s+([A-Z]{3})/ ) { print "hour = $1 minute = $2 zone = $3\n"; } 각 후보들마다 그룹 번호가 동일하게 시작

Korean Perl Workshop 2012 85

1 1 2 2 3

Page 86: KPW2012 조금 깊이 들여다보는 정규표현식

• 각 후보 패턴마다 그룹의 개수가 다를 경우, 리셋 그룹 이후 나타나는 그룹은 가장 높은 번호의 다음 번호부터 할당

• 주의: Perl 5.14 전 버전에는 버그 • 의도한 대로 캡처되지 않음

• 캡처 그룹이 가장 많은 후보 패턴을 제일 먼저 적어주거나

• 빈 그룹 ()을 넣어 모든 후보의 그룹 개수를 동일하게 만들 것

Korean Perl Workshop 2012 86

Page 87: KPW2012 조금 깊이 들여다보는 정규표현식

PREMATCH, MATCH, POSTMATCH

$` $& $'

• 정규식 연산에 성능 저하를 가져옴

• 코드 내에 한 번이라도 사용되면, 모든 정규식 연산마다 저 변수들을 세팅하는 과정을 거침

Korean Perl Workshop 2012 87

* 코드 출처: www.effectiveperlprogramming.com

Page 88: KPW2012 조금 깊이 들여다보는 정규표현식

'My cat is Buster Bean' =~ m/Buster/; print "I matched $&\n"; # 여기서 매치 변수를 사용해버렸기 때문에 while (<>) { next unless /Bean/; # 매치할 때마다 매번 오버헤드가 발생 }

Korean Perl Workshop 2012 88

Page 89: KPW2012 조금 깊이 들여다보는 정규표현식

따라서, 저 세 가지 변수는

• 전혀 사용하지 않거나

• 한 번이라도 사용했다면, 그 다음은 마음대로 사용해도 됨

Korean Perl Workshop 2012 89

Page 90: KPW2012 조금 깊이 들여다보는 정규표현식

대신 다음 변수들을 사용

• ${^PREMATCH} $` 역할 • ${^MATCH} $& • ${^POSTMATCH} $' • /p flag 명시

• /p flag가 있는 연산에서만 오버헤드 발생

Korean Perl Workshop 2012 90

Page 91: KPW2012 조금 깊이 들여다보는 정규표현식

'My cat is Buster Bean' =~ m/\s\w+\sBean/p; # /p 옵션 사용 say "I matched ${^MATCH}"; while (<>) { next unless /Bean/; # 오버헤드 없음 }

Korean Perl Workshop 2012 91

Page 92: KPW2012 조금 깊이 들여다보는 정규표현식

5.10 전 버전 - 캡처 그룹과 매칭 변수로 대체

• /pattern/ + $` 대신 /(.*?)pattern/ + $1 • /pattern/ + $& 대신 /(pattern)/ + $1 • /pattern/ + $' 대신 /pattern(.*)/ + $+

• use English qw(-no_match_vars)

• 로드한 외부 모듈에서 사용해 버리면 역시 소용 없음

Korean Perl Workshop 2012 92

Page 93: KPW2012 조금 깊이 들여다보는 정규표현식

Possessive quantifier

'abcdZ' =~ /[a-d]+Z/;

93 Korean Perl Workshop 2012

Page 94: KPW2012 조금 깊이 들여다보는 정규표현식

'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치

94 Korean Perl Workshop 2012

Page 95: KPW2012 조금 깊이 들여다보는 정규표현식

'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치

• Z는 'Z'에 일치

95 Korean Perl Workshop 2012

Page 96: KPW2012 조금 깊이 들여다보는 정규표현식

'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치

• Z는 'Z'에 일치

• 끝~

96 Korean Perl Workshop 2012

Page 97: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열

Korean Perl Workshop 2012 97

Page 98: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 • [a-d]+ 는 일단 'abcda' 에 일치

Korean Perl Workshop 2012 98

Page 99: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 • [a-d]+ 는 일단 'abcda' 에 일치 • Z가 일치될 문자열이 남아 있지 않으므로

Korean Perl Workshop 2012 99

Page 100: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 • [a-d]+ 는 일단 'abcda' 에 일치 • Z가 일치될 문자열이 남아 있지 않으므로

– 'a'를 내어놓고 재시도

Korean Perl Workshop 2012 100

Page 101: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 • [a-d]+ 는 일단 'abcda' 에 일치 • Z가 일치될 문자열이 남아 있지 않으므로

– 'a'를 내어놓고 재시도 – 'd'를 내어놓고 재시도 – …

Korean Perl Workshop 2012 101

Page 102: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 • [a-d]+ 는 일단 'abcda' 에 일치 • Z가 일치될 문자열이 남아 있지 않으므로

– 'a'를 내어놓고 재시도 – 'd'를 내어놓고 재시도 – …

• 'bcda'를 대상으로 처음부터 다시 – …

Korean Perl Workshop 2012 102

Page 103: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]+Z/;

Korean Perl Workshop 2012 103

Page 104: KPW2012 조금 깊이 들여다보는 정규표현식

;;;;;;;

그, 그만…

Korean Perl Workshop 2012 104

Page 105: KPW2012 조금 깊이 들여다보는 정규표현식

• 독점적인 수량자

?+ *+ ++ {2,5}+

• 일치에 성공한 부분은 백트래킹하지 않음

Korean Perl Workshop 2012 105

Page 106: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]++Z/;

Korean Perl Workshop 2012 106

Page 107: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치

Korean Perl Workshop 2012 107

Page 108: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치

• Z는 일치에 실패

Korean Perl Workshop 2012 108

Page 109: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치

• Z는 일치에 실패

• 백트래킹하지 않고 곧바로 실패 판정

Korean Perl Workshop 2012 109

Page 110: KPW2012 조금 깊이 들여다보는 정규표현식

'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치

• Z는 일치에 실패

• 백트래킹하지 않고 곧바로 실패 판정

• 단, 여기서 끝은 아님 – 문자열의 다음 위치에서 재시도

Korean Perl Workshop 2012 110

Page 111: KPW2012 조금 깊이 들여다보는 정규표현식

Korean Perl Workshop 2012 111

Page 112: KPW2012 조금 깊이 들여다보는 정규표현식

• 주의 'aaaaa' =~ /a++a/; 이것은 일치하지 않는다

• a++가 'aaaaa'에 일치해버리기 때문에 뒤에 a가 일치할 문자열이 남지 않음

• 아무 때나 Greedy 수량자 대신 사용할 수는 없음

Korean Perl Workshop 2012 112

Page 113: KPW2012 조금 깊이 들여다보는 정규표현식

• 독점적 수량자를 써도 괜찮은지 판단 'aaaaa' =~ / a++ a /x; # No 'aaaaa' =~ / a++ b /x; # Yes

Korean Perl Workshop 2012 113

Page 114: KPW2012 조금 깊이 들여다보는 정규표현식

• 독점적 수량자를 써도 괜찮은지 판단 'aaaaa' =~ / a++ a /x; # No 'aaaaa' =~ / a++ b /x; # Yes

• 수량자가 적용되는 부분의 패턴이, 뒤에 오는 패턴과

일치하지 않으면 괜찮음

Korean Perl Workshop 2012 114

Page 115: KPW2012 조금 깊이 들여다보는 정규표현식

백트래킹을 하지 않는 부분식

• 독점적 수량자의 일반형

/[a-d]++Z/ /(?>[a-d]+)Z/; • 주의 /(?>[a-d])+Z/; # 다르다

Korean Perl Workshop 2012 115

Page 116: KPW2012 조금 깊이 들여다보는 정규표현식

/r flag in substitution

$str =~ s/pattern/replacement/ • $str 의 내용을 변경

• 치환 횟수를 반환

$str =~ s/pattern/replacement/r • $str 을 변경하지 않음

• 복제본을 만들어서 복제본을 변경

• 변경된 복제본 문자열을 반환

Korean Perl Workshop 2012 116

Page 117: KPW2012 조금 깊이 들여다보는 정규표현식

• 기존 코드 my $old = 'hello'; (my $new = $old) =~ s/h/H/; # 괄호 필수!

• 새 코드 my $old = 'hello'; my $new = $old =~ s/h/H/r;

Korean Perl Workshop 2012 117

Page 118: KPW2012 조금 깊이 들여다보는 정규표현식

그게 뭐야

Korean Perl Workshop 2012 118

Page 119: KPW2012 조금 깊이 들여다보는 정규표현식

• 좀 더 유용한 예 my @in = qw( Bu1s5ter Mi6mi Roscoe Gin98ger El123la ); # @in의 각 원소에서 숫자를 제거하여 # @out 배열에 저장하고 싶다 my @out = map { my $s = $_; $s =~ s/\d+//g; $s } @in; # 원소를 일일이 복사해야 함

Korean Perl Workshop 2012 119

* 코드 출처: www.effectiveperlprogramming.com

Page 120: KPW2012 조금 깊이 들여다보는 정규표현식

• 좀 더 유용한 예 my @in = qw( Bu1s5ter Mi6mi Roscoe Gin98ger El123la ); # @in의 각 원소에서 숫자를 제거하여 # @out 배열에 저장하고 싶다 my @out = map { my $s = $_; $s =~ s/\d+//g; $s } @in; # 원소를 일일이 복사해야 함 my @out = map { s/\d+//gr } @in;

Korean Perl Workshop 2012 120

Page 121: KPW2012 조금 깊이 들여다보는 정규표현식

Named Subpattern

"수"에 일치되는 정규식의 예 (3, -7, .25, 12.34, -5.67e10 등)

/^ [+-]?\ * # 먼저, 부호와 공백에 매치 ( # 그 다음 정수 또는 소수의 유효숫자부에 매치 \d+ # a로 시작하면서... ( \.\d* # a.b 또는 a. 형태의 유효숫자 )? # ?는 a 형태의 정수가 오는 경우를 고려한 것 |\.\d+ # .b 형태의 유효숫자 ) ([eE][+-]?\d+)? # 추가적으로 올 수 있는 지수부에 매치 $/x;

Korean Perl Workshop 2012 121

* 코드 출처: perlretut

Page 122: KPW2012 조금 깊이 들여다보는 정규표현식

패턴을 정의하고 이름을 붙인 후 재사용 /^ (?&osg)\ * ( (?&int)(?&dec)? | (?&dec) ) (?: [eE](?&osg)(?&int) )? $ (?(DEFINE) (?<osg>[-+]?) # 생략 가능한 부호 (?<int>\d++) # 정수 (?<dec>\.(?&int)) # 소수부 )/x;

Korean Perl Workshop 2012 122

Page 123: KPW2012 조금 깊이 들여다보는 정규표현식

Recursive Pattern

• 부등호로 둘러싸인 문자열에 일치 /<.*?>/ 또는 /<[^<>]>/

Korean Perl Workshop 2012 123

Page 124: KPW2012 조금 깊이 들여다보는 정규표현식

• 부등호로 둘러싸인 문자열에 일치 /<.*?>/ 또는 /<[^<>]>/

• 중첩된 형태에도 일치 "< … < … > … < … < … > > … >"

/????/

Korean Perl Workshop 2012 124

Page 125: KPW2012 조금 깊이 들여다보는 정규표현식

• 정규식은 정규문법으로 생성되는 문자열을 표현

• 문맥 무관 문법으로 생성되는 문자열을 표현하는 것에는 한계가 있음 – Balanced text

– Program code

• Text::Balanced

• Regexp::Common

• Parser용 모듈들

Korean Perl Workshop 2012 125

Page 126: KPW2012 조금 깊이 들여다보는 정규표현식

• 재귀 패턴을 사용한 정규식

중첩되지 않는 패턴 <[^<>]++>

Korean Perl Workshop 2012 126

Page 127: KPW2012 조금 깊이 들여다보는 정규표현식

• 재귀 패턴을 사용한 정규식

중첩되지 않는 패턴 <[^<>]++> 중첩된 패턴 = < > 안에 부등호를 제외한 것들 또는 패턴 이 반복 Korean Perl Workshop 2012 127

Page 128: KPW2012 조금 깊이 들여다보는 정규표현식

/ < > /x; # 부등호 안에

Korean Perl Workshop 2012 128

Page 129: KPW2012 조금 깊이 들여다보는 정규표현식

/ < > /x; # 부등호 안에 / < [^<>]++ > /x; # 부등호 외의 것들

Korean Perl Workshop 2012 129

Page 130: KPW2012 조금 깊이 들여다보는 정규표현식

/ < > /x; # 부등호 안에 / < [^<>]++ > /x; # 부등호 외의 것들 / (< [^<>]++ | (?1) >) /x; # 또는 패턴이

Korean Perl Workshop 2012 130

Page 131: KPW2012 조금 깊이 들여다보는 정규표현식

/ < > /x; # 부등호 안에 / < [^<>]++ > /x; # 부등호 외의 것들 / (< [^<>]++ | (?1) >) /x; # 또는 패턴이 / (< (?: [^<>]++ | (?1) )* >) /x; # 반복

Korean Perl Workshop 2012 131

Page 132: KPW2012 조금 깊이 들여다보는 정규표현식

my $string =<<"HERE"; I have some <brackets in <nested brackets> > and <another group <nested once <nested twice> > > and that's it. HERE my @groups = $string =~ m/ < (?: [^<>]++ | (?1) )* > )/xg;

Korean Perl Workshop 2012 132

* 코드 출처: perlfaq6

Page 133: KPW2012 조금 깊이 들여다보는 정규표현식

좋죠?

Korean Perl Workshop 2012 133

Page 134: KPW2012 조금 깊이 들여다보는 정규표현식

그러니

Korean Perl Workshop 2012 134

Page 135: KPW2012 조금 깊이 들여다보는 정규표현식

호스팅 업체 분들,

Perl 5.14 이상으로 설치 좀 굽신굽신

Korean Perl Workshop 2012 135

Page 136: KPW2012 조금 깊이 들여다보는 정규표현식

자잘한 팁들

Korean Perl Workshop 2012 136

Page 137: KPW2012 조금 깊이 들여다보는 정규표현식

빈 패턴은 항상 일치

/()/

언제나 일치하며, 캡처됨

/(?!)/

언제나 실패하는 패턴

Korean Perl Workshop 2012 137

Page 138: KPW2012 조금 깊이 들여다보는 정규표현식

• 세 단어가 순서 무관하게 가까이 붙어 있는 경우를 검색

… word1 … word3 … … … word2 …

(8단어 이내에 세 단어 존재)

Korean Perl Workshop 2012 138

* 코드 출처: 한 권으로 끝내는 정규표현식

Page 139: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x

Korean Perl Workshop 2012 139

Page 140: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 140

Page 141: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 141

Page 142: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 142

Page 143: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 143

이제부터는 아무 단어나 일치 가능

Page 144: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 144

최대 8번까지 단어들을 일치시킨 후

Page 145: KPW2012 조금 깊이 들여다보는 정규표현식

… word1 … word3 … … … word2 …

/ \b (?: (?>word1()|word2()|word3()|(?>\1|\2|\3)\w+)\b\W*? ){3,8} \1\2\3 /x 일단 word1 이 일치하면 ()가 같이 일치하고

\1은 그때부터 일치

Korean Perl Workshop 2012 145

전체 패턴이 일치하기 위해서는 여기를 통과해야 함 즉 word1, word2, word3 이 한번씩 일치되었어야 함

Page 146: KPW2012 조금 깊이 들여다보는 정규표현식

Korean Perl Workshop 2012 146

Page 147: KPW2012 조금 깊이 들여다보는 정규표현식

정규식으로만 해결하려 하지 말자

my $str = '1 <b>2</b> 3 4 <b>5 6 7</b> 8'; # 볼드체로 표시되는 숫자들만 추출하고 싶다 # 2, 5, 6, 7 # "5 6 7"을 추출하는 게 아니라서 까다롭다

Korean Perl Workshop 2012 147

Page 148: KPW2012 조금 깊이 들여다보는 정규표현식

my $str = '1 <b>2</b> 3 4 <b>5 6 7</b> 8'; # 볼드체로 표시되는 숫자들만 추출하고 싶다 # 2, 5, 6, 7 my @numbers = ( $str =~ m|\d+(?=(?:(?!<b>).)*</b>)|g );

Korean Perl Workshop 2012 148

Page 149: KPW2012 조금 깊이 들여다보는 정규표현식

my $str = '1 <b>2</b> 3 4 <b>5 6 7</b> 8'; # 볼드체로 표시되는 숫자들만 추출하고 싶다 # 2, 5, 6, 7 while ( $str =~ m|<b>(.*?)</b>|gs ) { push @numbers, ($& =~ /\d+/g); } 쉽고, 백트래킹 등을 생각하면 효율도 이게 낫다

Korean Perl Workshop 2012 149

Page 150: KPW2012 조금 깊이 들여다보는 정규표현식

grep

grep '\d\{4\}\s\+' file1 file2 백슬래시 쓰느라 지겨우시죠?

Korean Perl Workshop 2012 150

Page 151: KPW2012 조금 깊이 들여다보는 정규표현식

grep '\d\{4\}\s\+' file1 file2 grep -P '\d{4}\s+' file1 file2 Perl 정규식을 사용 가능

Korean Perl Workshop 2012 151

Page 152: KPW2012 조금 깊이 들여다보는 정규표현식

vim

/\(a\|b\)\+

• vim의 패턴 해석 방식 4가지 – \V : 백슬래시만 특수하게 해석 – \M : set nomagic – \m : set magic – \v : "very magic"

• Perl 정규식과 비슷해짐 /\v(a|b)+

Korean Perl Workshop 2012 152

Page 153: KPW2012 조금 깊이 들여다보는 정규표현식

• vim의 Lookaround – \@= \@! Lookahead – \@<= \@<! Lookbehind

• 예 /foo\(bar\)\@! "bar"가 뒤에 오지 않는 "foo"

:help pattern :help perl-patterns

Korean Perl Workshop 2012 153

Page 154: KPW2012 조금 깊이 들여다보는 정규표현식

Regexp::Debugger

• Damian Conway

• CPAN

use Regexp::Debugger; 또는

$ rxrx

Korean Perl Workshop 2012 154

Page 155: KPW2012 조금 깊이 들여다보는 정규표현식

"감사합니다" =~

/(Q(&A)?)*/

Korean Perl Workshop 2012 155