1. 조금 깊이 들여다보는
qr/정규표현식/
Korean Perl Workshop 2012
2012. 10. 20.
박근영
@gypark gypark@gmail.com
http://gypark.pe.kr/wiki/Perl
2. 목차
• 흔히 겪는 오류와 실수
• Perl 5.10 이후에 도입된 정규식 문법
• 자잘한 팁들
Korean Perl Workshop 2012 2
3. 이 문서의 내용과 코드는 주로…
• perlretut (regular expression tutorial)
– 번역: http://gypark.pe.kr/wiki/Perl/정규표현식
• perlre
• 손에 잡히는 정규표현식
– 벤 포터, 김경수 번역, 인사이트
• 한 권으로 끝내는 정규표현식
– 잰 고이바에르츠 외, 김지원 번역, 한빛미디어
• WWW
…등에서 발췌
Korean Perl Workshop 2012 3
4. 흔히 겪는 오류와 실수
"어째서 일치하지 않을까요?"
"어째서 여기에 일치해 버릴까요?"
Korean Perl Workshop 2012 4
5. 정규식의 어려움
• 일치해야 될 문자열에 일치하는 정규식을
만드는 것은 비교적 쉽다
Korean Perl Workshop 2012 5
6. • 일치해야 될 문자열에 일치하는 정규식을
만드는 것은 비교적 쉽다
• 일치하지 말아야 할 문자열에 일치하지 않
는 정규식을 만드는 것이 어렵다
Korean Perl Workshop 2012 6
7. • 일치해야 될 문자열에 일치하는 정규식을
만드는 것은 비교적 쉽다
• 일치하지 말아야 할 문자열에 일치하지 않
는 정규식을 만드는 것이 어렵다
– 경우의 수가 무한함
– 테스트하기 힘듦
– 상황에 따라 적절한 타협이 필요
Korean Perl Workshop 2012 7
8. 문자열의 앞에서부터 일치
• 정규표현식 일치 검사의 첫번째 원칙
“문자열에서 가능한 한
가장 앞부분에서 일치시킨다”
Korean Perl Workshop 2012 8
9. • 간단한 예
"cats and dogs" =~ / dog | cat | bird /x;
* 코드 출처:
Korean Perl Workshop 2012 perlretut
9
10. • 간단한 예
"cats and dogs" =~ / dog | cat | bird /x;
• 후보들의 순서에 무관하게, 앞에서부터 일치
Korean Perl Workshop 2012 10
11. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs'
Korean Perl Workshop 2012 11
12. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+"/;
Greedy quantifier
Korean Perl Workshop 2012 12
13. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?"/;
Non-greedy quantifier로 교체
Korean Perl Workshop 2012 13
14. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?"/;
성공!
Korean Perl Workshop 2012 14
15. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?" dogs/;
뒤에 조건이 추가
Korean Perl Workshop 2012 15
16. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?" dogs/;
우리가 원한 것
이것을 기대하지만…
Korean Perl Workshop 2012 16
17. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?" dogs/;
실제로 일치하는 부분
우리가 원한 것
???
Korean Perl Workshop 2012 17
18. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/".+?" dogs/;
실제로 일치하는 부분
Non-greedy 수량자는 정규식이 일치할 때까지
문자열을 소모하며 일치부를 확장지킨다.
Korean Perl Workshop 2012 18
19. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/"[^"]+" dogs/;
/./ 대신에 따옴표를 제외한 문자들만 일치하도록 수정
Korean Perl Workshop 2012 19
20. • 수량자와 같이 사용할 때
'"10" cats and "20" dogs' =~ m/"[^"]+" dogs/;
성공
Korean Perl Workshop 2012 20
21. • 경계가 한 글자가 아니면……
"<b>10</b> cats and <b>20</b> dogs"
Korean Perl Workshop 2012 21
22. • 경계가 한 글자가 아니면……
"<b>10</b> cats and <b>20</b> dogs"
=~
m'<b>((?!</b>).)+</b> dogs';
부정 전방탐색
Negative Lookahead
Korean Perl Workshop 2012 22
23. 같은 위치에서는 왼쪽 후보부터
"Her name is Janet." =~ / Jane | Janet /x;
이 문자열은…
* 코드 출처:
Korean Perl Workshop 2012 perlretut
23
24. "Her name is Janet." =~ / Jane | Janet /x;
이 문자열은…
절대로 'Janet'에 일치하지 않을 것임
Korean Perl Workshop 2012 24
25. "Her name is Janet." =~
/ Janet | Jane /x
/ bJaneb | bJanetb /x
/ bJanet?b /x
정규식 리터럴에서는 이런 실수가 적지만,
패턴이 변수에 들어가 있으면 눈에 띄지 않음
Korean Perl Workshop 2012 25
26. 실패하면 거기서 끝나지 않는다
• 일치에 실패하면, 문자열의 다음 글자부터
다시 일치를 시도함
Korean Perl Workshop 2012 26
27. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
"TGA" codon의 위치를 검색
* 코드 출처:
Korean Perl Workshop 2012 perlretut
27
28. # "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
29. # "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
30. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
2차 시도
세 글자씩 끊어가며 검색
Korean Perl Workshop 2012 30
31. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18
TGA at 23 ???
… 어째서?
Korean Perl Workshop 2012 31
32. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18 마지막으로 성공한 후
Korean Perl Workshop 2012 32
33. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18 마지막으로 성공한 후
그 직후부터 일치를 시도하여 실패하고
Korean Perl Workshop 2012 33
34. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18 마지막으로 성공한 후
그 직후부터 일치를 시도하여 실패하고
그 다음 글자부터 재시도하여 실패하고
Korean Perl Workshop 2012 34
35. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18 마지막으로 성공한 후
그 직후부터 일치를 시도하여 실패하고
그 다음 글자부터 재시도하여 실패하고
TGA at 23 그 다음 글자부터 재시도하여 성공
Korean Perl Workshop 2012 35
36. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /G(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
3차 시도
/G/ - /g flag를 사용하여 일치된 마지막 지점
Korean Perl Workshop 2012 36
37. # "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";
while ( $dna =~ /G(www)*?TGA/g ) {
print "TGA at ", pos $dna, "n";
}
TGA at 18 성공
앵커에 일치해야 하기 때문에,
그 다음 글자부터 진행할 수 없다
Korean Perl Workshop 2012 37
39. “…하지 않은 것”을 찾기
• 완전한 단어 “cat”에 일치
/bcatb/
Korean Perl Workshop 2012 39
40. • 완전한 단어 “cat”에 일치
/bcatb/
• 어딘가에 포함되어 있는 “cat”?
Korean Perl Workshop 2012 40
41. • 완전한 단어 “cat”에 일치
/bcatb/
• 어딘가에 포함되어 있는 “cat”?
• “cat”을 제외한 모든 단어?
Korean Perl Workshop 2012 41
42. • 완전한 단어 “cat”에 일치
/bcatb/
• 어딘가에 포함되어 있는 “cat”?
• “cat”을 제외한 모든 단어?
• “cat”이 포함되지 않은 단어?
Korean Perl Workshop 2012 42
43. • 어딘가에 포함되어 있는 “cat”
bobcat, category, staccato, 123cat456 …
* 코드 출처:
Korean Perl Workshop 2012 한 권으로 끝내는 정규표현식, 67
43
44. • 어딘가에 포함되어 있는 “cat”
bobcat, category, staccato, 123cat456 …
• 오답
/BcatB/
Korean Perl Workshop 2012 44
45. • 어딘가에 포함되어 있는 “cat”
bobcat, category, staccato, 123cat456 …
• 오답
/BcatB/
• 정답
/Bcat|catB/
Korean Perl Workshop 2012 45
46. • “cat”을 제외한 모든 단어
snake, bat, dog, bobcat, …
* 코드 출처:
Korean Perl Workshop 2012 한 권으로 끝내는 정규표현식, 372
46
47. • “cat”을 제외한 모든 단어
snake, bat, dog, bobcat, …
• 흔히 보이는 오답
/b[^cat]+b/
– [^…]를 단어를 배제하는 용도로 쓰면 안 됨
Korean Perl Workshop 2012 47
48. • “cat”을 제외한 모든 단어
snake, bat, dog, bobcat, …
• 흔히 보이는 오답
/b[^cat]+b/
– [^…]를 단어를 배제하는 용도로 쓰면 안 됨
• 마찬가지
/b[^c][^a][^t]b/
Korean Perl Workshop 2012 48
49. • “cat”을 제외한 모든 단어
snake, bat, dog, bobcat, …
• 정답
/b(?!catb)w+/
Korean Perl Workshop 2012 49
50. • “cat”이 포함되어 있지 않은 모든 단어
snake, bat, dog, bobcat, …
/b(?:(?!cat)w)+b/
* 코드 출처:
Korean Perl Workshop 2012 한 권으로 끝내는 정규표현식
50
51. “일치하지 않음” vs “아닌 것에 일치함”
$str = 'I paid $30 for 100 apples';
* 코드 출처:
Korean Perl Workshop 2012 손에 잡히는 정규표현식, 93
51
52. $str = 'I paid $30 for 100 apples';
# 가격에만 일치
$str =~ /$d+/;
Korean Perl Workshop 2012 52
53. $str = 'I paid $30 for 100 apples';
# '$'는 제외하고 숫자에만 일치
$str =~ /(?<=$)d+/; # 후방탐색
Korean Perl Workshop 2012 53
54. my $str = 'I paid $30 for 100 apples';
# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색
Korean Perl Workshop 2012 54
55. my $str = 'I paid $30 for 100 apples';
# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색
# 실패
Korean Perl Workshop 2012 55
56. my $str = 'I paid $30 for 100 apples';
# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색
# 실패
$str =~ /b(?<!$)d+/; # 앵커가 필요함
Korean Perl Workshop 2012 56
57. 전후방탐색의 활용
(?<=before)match(?=after)
이 형태만 생각하기 쉬움
Korean Perl Workshop 2012 57
58. 일련의 숫자, 그 뒤에 일련의 문자 형태
# 1a, 1ab, 123abcd, ....
/^d+[a-z]+$/
Korean Perl Workshop 2012 58
60. • 정규식 안의 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
61. • 정규식과 코드의 협동
/^d+[a-z]+$/
and length($_) >= 4
and length($_) <= 6
Korean Perl Workshop 2012 61
62. • 전방탐색
/^(?=.{4,6}$)d+[a-z]+$/
둘 이상의 조건을 동시에 검사
Korean Perl Workshop 2012 62
63. 전방탐색과 조건식 결합
올바른 우편번호 찾기
11111 (o)
22222 (o)
33333- (x)
44444-4444 (o)
* 코드 출처:
Korean Perl Workshop 2012 손에 잡히는 정규표현식, 102
63
64. 올바른 우편번호 찾기
11111 (o)
22222 (o)
33333- (x)
44444-4444 (o)
/d{5}(-d{4})?/
세번째 문자열을 걸러내지 못함
Korean Perl Workshop 2012 64
65. 올바른 우편번호 찾기
11111 (o)
22222 (o)
33333- (x)
44444-4444 (o)
/d{5}(?(?=-)-d{4})/
전방탐색이 성공하면 그 뒤의 패턴도 검사
Korean Perl Workshop 2012 65
66. Case shifting
Q L l U u E
– Perl에서는 큰따옴표 문자열 문법의 일부
– 정규표현식 문법이 아님
Korean Perl Workshop 2012 66
74. /x flag
$str = "abc - 123";
$str =~ /S+ - d+/;
아주 잘 일치함
Korean Perl Workshop 2012 74
75. $str = "abc - 123";
$str =~ /
S+ # 단어
- # 대시
d+ # 숫자
/x;
이것은 일치하지 않는다!
Korean Perl Workshop 2012 75
76. $str = "abc - 123";
$str =~ /
S+ # 단어,공백
- # 대시,공백
d+ # 숫자
/x;
스페이스는 /[ ]/ 또는 / /로 바꿔야 되는 걸 잊지 말자
Korean Perl Workshop 2012 76
77. 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
78. N metacharacter
/./
임의의 캐릭터 하나
– /s 옵션이 있을 때는 뉴라인"n"에 일치
– 없을 때는 뉴라인에 일치하지 않음
/N/
/s 옵션에 무관하게 항상 뉴라인을 제외한
임의의 캐릭터 하나
Korean Perl Workshop 2012 78
79. Relative backreferences
# 오동작
my $a99a = '([a-z])(d)g2g1'; # a11a, g22g, ...
my $line = 'code=e99e';
if ( $line =~ /^(w+)=$a99a$/ ) {
print "$1 is validn";
}
앞에 괄호가 추가되면서 번호가 안 맞는다
* 코드 출처:
Korean Perl Workshop 2012 perlretut
79
80. # 오동작
my $a99a = '([a-z])(d)g2g1'; # a11a, g22g, ...
my $line = 'code=e99e';
if ( $line =~ /^(w+)=$a99a$/ ) {
print "$1 is validn";
}
my $a99a = '([a-z])(d)g{-1}g{-2}'
현재 위치 기준.
Korean Perl Workshop 2012 80
81. Named backreferences
• 매치되는 그룹에 이름을 붙임
• 앞의 예 다시
my $a99a =
'(?<char>[a-z])(?<digit>d)g{digit}g{char}';
Korean Perl Workshop 2012 81
82. • 그룹의 순서가 서로 다른 패턴을 일괄처리
$fmt1 = '(?<y>dddd)-(?<m>dd)-(?<d>dd)';
$fmt2 = '(?<m>dd)/(?<d>dd)/(?<y>dddd)';
$fmt3 = '(?<d>dd).(?<m>dd).(?<y>dddd)';
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 perlretut
82
83. Branch Reset
$time = '2305';
if ( $time =~ /(dd|d):(dd)|(dd)(dd)/ )
{
print "hour = $1 minute = $2n"; # ??
print "hour = $3 minute = $4n"; # ??
}
몇 번째 그룹에 캡처가 될 지 모름
defined 검사 필요
* 코드 출처:
Korean Perl Workshop 2012 perlretut
83
85. $time = '2305 GMT';
if ( $time =~
/(?|(dd|d):(dd)|(dd)(dd))s+([A-Z]{3})/
) 1 2 1 2 3
{
print "hour = $1 minute = $2 zone = $3n";
}
각 후보들마다 그룹 번호가 동일하게 시작
Korean Perl Workshop 2012 85
86. • 각 후보 패턴마다 그룹의 개수가 다를 경우, 리셋 그룹
이후 나타나는 그룹은 가장 높은 번호의 다음 번호부터
할당
• 주의: Perl 5.14 전 버전에는 버그
• 의도한 대로 캡처되지 않음
• 캡처 그룹이 가장 많은 후보 패턴을 제일 먼저 적어주거나
• 빈 그룹 ()을 넣어 모든 후보의 그룹 개수를 동일하게 만들 것
Korean Perl Workshop 2012 86
87. PREMATCH, MATCH, POSTMATCH
$` $& $'
• 정규식 연산에 성능 저하를 가져옴
• 코드 내에 한 번이라도 사용되면, 모든 정규식 연산마다
저 변수들을 세팅하는 과정을 거침
* 코드 출처:
Korean Perl Workshop 2012 www.effectiveperlprogramming.com
87
88. 'My cat is Buster Bean' =~ m/Buster/;
print "I matched $&n";
# 여기서 매치 변수를 사용해버렸기 때문에
while (<>) {
next unless /Bean/;
# 매치할 때마다 매번 오버헤드가 발생
}
Korean Perl Workshop 2012 88
89. 따라서, 저 세 가지 변수는
• 전혀 사용하지 않거나
• 한 번이라도 사용했다면, 그 다음은 마음대로 사용해도
됨
Korean Perl Workshop 2012 89
90. 대신 다음 변수들을 사용
• ${^PREMATCH} $` 역할
• ${^MATCH} $&
• ${^POSTMATCH} $'
• /p flag 명시
• /p flag가 있는 연산에서만 오버헤드 발생
Korean Perl Workshop 2012 90
91. 'My cat is Buster Bean' =~ m/sw+sBean/p;
# /p 옵션 사용
say "I matched ${^MATCH}";
while (<>) {
next unless /Bean/; # 오버헤드 없음
}
Korean Perl Workshop 2012 91
92. 5.10 전 버전 - 캡처 그룹과 매칭 변수로 대체
• /pattern/ + $` 대신 /(.*?)pattern/ + $1
• /pattern/ + $& 대신 /(pattern)/ + $1
• /pattern/ + $' 대신 /pattern(.*)/ + $+
• use English qw(-no_match_vars)
• 로드한 외부 모듈에서 사용해 버리면 역시 소용 없음
Korean Perl Workshop 2012 92
98. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
Korean Perl Workshop 2012 98
99. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
Korean Perl Workshop 2012 99
100. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
– 'a'를 내어놓고 재시도
Korean Perl Workshop 2012 100
101. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
– 'a'를 내어놓고 재시도
– 'd'를 내어놓고 재시도
– …
Korean Perl Workshop 2012 101
102. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
– 'a'를 내어놓고 재시도
– 'd'를 내어놓고 재시도
– …
• 'bcda'를 대상으로 처음부터 다시
– …
Korean Perl Workshop 2012 102
112. • 주의
'aaaaa' =~ /a++a/;
이것은 일치하지 않는다
• a++가 'aaaaa'에 일치해버리기 때문에 뒤에 a가 일치할 문자열이 남
지 않음
• 아무 때나 Greedy 수량자 대신 사용할 수는 없음
Korean Perl Workshop 2012 112
113. • 독점적 수량자를 써도 괜찮은지 판단
'aaaaa' =~ / a++ a /x; # No
'aaaaa' =~ / a++ b /x; # Yes
Korean Perl Workshop 2012 113
114. • 독점적 수량자를 써도 괜찮은지 판단
'aaaaa' =~ / a++ a /x; # No
'aaaaa' =~ / a++ b /x; # Yes
• 수량자가 적용되는 부분의 패턴이, 뒤에 오는 패턴과
일치하지 않으면 괜찮음
Korean Perl Workshop 2012 114
115. 백트래킹을 하지 않는 부분식
• 독점적 수량자의 일반형
/[a-d]++Z/
/(?>[a-d]+)Z/;
• 주의
/(?>[a-d])+Z/; # 다르다
Korean Perl Workshop 2012 115
116. /r flag in substitution
$str =~ s/pattern/replacement/
• $str 의 내용을 변경
• 치환 횟수를 반환
$str =~ s/pattern/replacement/r
• $str 을 변경하지 않음
• 복제본을 만들어서 복제본을 변경
• 변경된 복제본 문자열을 반환
Korean Perl Workshop 2012 116
117. • 기존 코드
my $old = 'hello';
(my $new = $old) =~ s/h/H/; # 괄호 필수!
• 새 코드
my $old = 'hello';
my $new = $old =~ s/h/H/r;
Korean Perl Workshop 2012 117
119. • 좀 더 유용한 예
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 www.effectiveperlprogramming.com
119
120. • 좀 더 유용한 예
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
121. 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 perlretut
121
122. 패턴을 정의하고 이름을 붙인 후 재사용
/^ (?&osg) * ( (?&int)(?&dec)? | (?&dec) )
(?: [eE](?&osg)(?&int) )? $
(?(DEFINE)
(?<osg>[-+]?) # 생략 가능한 부호
(?<int>d++) # 정수
(?<dec>.(?&int)) # 소수부
)/x;
Korean Perl Workshop 2012 122
125. • 정규식은 정규문법으로 생성되는 문자열을 표현
• 문맥 무관 문법으로 생성되는 문자열을 표현하는 것에는
한계가 있음
– Balanced text
– Program code
• Text::Balanced
• Regexp::Common
• Parser용 모듈들
Korean Perl Workshop 2012 125
126. • 재귀 패턴을 사용한 정규식
중첩되지 않는 패턴
<[^<>]++>
Korean Perl Workshop 2012 126
127. • 재귀 패턴을 사용한 정규식
중첩되지 않는 패턴
<[^<>]++>
중첩된 패턴 =
< > 안에
부등호를 제외한 것들
또는 패턴
이 반복
Korean Perl Workshop 2012 127
128. / < > /x; # 부등호 안에
Korean Perl Workshop 2012 128
129. / < > /x; # 부등호 안에
/ < [^<>]++ > /x; # 부등호 외의 것들
Korean Perl Workshop 2012 129
130. / < > /x; # 부등호 안에
/ < [^<>]++ > /x; # 부등호 외의 것들
/ (< [^<>]++ | (?1) >) /x; # 또는 패턴이
Korean Perl Workshop 2012 130
132. 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 perlfaq6
132
151. grep 'd{4}s+' file1 file2
grep -P 'd{4}s+' file1 file2
Perl 정규식을 사용 가능
Korean Perl Workshop 2012 151
152. vim
/(a|b)+
• vim의 패턴 해석 방식 4가지
– V : 백슬래시만 특수하게 해석
– M : set nomagic
– m : set magic
– v : "very magic"
• Perl 정규식과 비슷해짐
/v(a|b)+
Korean Perl Workshop 2012 152
153. • vim의 Lookaround
– @= @! Lookahead
– @<= @<! Lookbehind
• 예
/foo(bar)@!
"bar"가 뒤에 오지 않는 "foo"
:help pattern
:help perl-patterns
Korean Perl Workshop 2012 153