ݺߣ

ݺߣShare a Scribd company logo
조금 깊이 들여다보는

qr/정규표현식/
  Korean Perl Workshop 2012
         2012. 10. 20.

            박근영
 @gypark gypark@gmail.com
 http://gypark.pe.kr/wiki/Perl
목차
• 흔히 겪는 오류와 실수

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

• 자잘한 팁들




Korean Perl Workshop 2012    2
이 문서의 내용과 코드는 주로…
• perlretut (regular expression tutorial)
    – 번역: http://gypark.pe.kr/wiki/Perl/정규표현식


• perlre

• 손에 잡히는 정규표현식
    – 벤 포터, 김경수 번역, 인사이트

• 한 권으로 끝내는 정규표현식
    – 잰 고이바에르츠 외, 김지원 번역, 한빛미디어

• WWW

…등에서 발췌

Korean Perl Workshop 2012                       3
흔히 겪는 오류와 실수




  "어째서 일치하지 않을까요?"
  "어째서 여기에 일치해 버릴까요?"



Korean Perl Workshop 2012   4
정규식의 어려움
• 일치해야 될 문자열에 일치하는 정규식을
  만드는 것은 비교적 쉽다




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

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




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

• 일치하지 말아야 할 문자열에 일치하지 않
  는 정규식을 만드는 것이 어렵다
    – 경우의 수가 무한함
    – 테스트하기 힘듦
    – 상황에 따라 적절한 타협이 필요

Korean Perl Workshop 2012   7
문자열의 앞에서부터 일치
• 정규표현식 일치 검사의 첫번째 원칙


 “문자열에서 가능한 한
가장 앞부분에서 일치시킨다”


Korean Perl Workshop 2012   8
• 간단한 예

"cats and dogs" =~ / dog | cat | bird /x;




                              * 코드 출처:
Korean Perl Workshop 2012       perlretut
                                            9
• 간단한 예

"cats and dogs" =~ / dog | cat | bird /x;


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




Korean Perl Workshop 2012                   10
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs'




Korean Perl Workshop 2012   11
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+"/;

        Greedy quantifier




Korean Perl Workshop 2012               12
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?"/;

        Non-greedy quantifier로 교체




Korean Perl Workshop 2012                13
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?"/;

        성공!




Korean Perl Workshop 2012                14
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?" dogs/;

        뒤에 조건이 추가




Korean Perl Workshop 2012                     15
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?" dogs/;
                            우리가 원한 것

        이것을 기대하지만…




Korean Perl Workshop 2012                     16
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?" dogs/;
실제로 일치하는 부분
                            우리가 원한 것




                 ???
Korean Perl Workshop 2012                     17
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/".+?" dogs/;
실제로 일치하는 부분


        Non-greedy 수량자는 정규식이 일치할 때까지
        문자열을 소모하며 일치부를 확장지킨다.




Korean Perl Workshop 2012                     18
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/"[^"]+" dogs/;

        /./ 대신에 따옴표를 제외한 문자들만 일치하도록 수정




Korean Perl Workshop 2012                       19
• 수량자와 같이 사용할 때

'"10" cats and "20" dogs' =~ m/"[^"]+" dogs/;

        성공




Korean Perl Workshop 2012                       20
• 경계가 한 글자가 아니면……

        "<b>10</b> cats and <b>20</b> dogs"




Korean Perl Workshop 2012                     21
• 경계가 한 글자가 아니면……

        "<b>10</b> cats and <b>20</b> dogs"
                    =~
          m'<b>((?!</b>).)+</b> dogs';

                 부정 전방탐색
                 Negative Lookahead




Korean Perl Workshop 2012                     22
같은 위치에서는 왼쪽 후보부터

"Her name is Janet." =~ / Jane | Janet /x;

   이 문자열은…




                              * 코드 출처:
Korean Perl Workshop 2012       perlretut
                                             23
"Her name is Janet." =~ / Jane | Janet /x;

   이 문자열은…
   절대로 'Janet'에 일치하지 않을 것임




Korean Perl Workshop 2012                    24
"Her name is Janet." =~
                            / Janet | Jane /x
                            / bJaneb | bJanetb /x
                            / bJanet?b /x

   정규식 리터럴에서는 이런 실수가 적지만,
   패턴이 변수에 들어가 있으면 눈에 띄지 않음



Korean Perl Workshop 2012                               25
실패하면 거기서 끝나지 않는다
• 일치에 실패하면, 문자열의 다음 글자부터
  다시 일치를 시도함




Korean Perl Workshop 2012   26
# "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC";

   "TGA" codon의 위치를 검색




                              * 코드 출처:
Korean Perl Workshop 2012       perlretut
                                            27
# "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
# "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
# "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
# "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
# "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
# "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
# "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
# "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
# "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
# "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
Korean Perl Workshop 2012   38
“…하지 않은 것”을 찾기
• 완전한 단어 “cat”에 일치

   /bcatb/




Korean Perl Workshop 2012   39
• 완전한 단어 “cat”에 일치

   /bcatb/

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




Korean Perl Workshop 2012   40
• 완전한 단어 “cat”에 일치

   /bcatb/

• 어딘가에 포함되어 있는 “cat”?
• “cat”을 제외한 모든 단어?




Korean Perl Workshop 2012   41
• 완전한 단어 “cat”에 일치

   /bcatb/

• 어딘가에 포함되어 있는 “cat”?
• “cat”을 제외한 모든 단어?
• “cat”이 포함되지 않은 단어?




Korean Perl Workshop 2012   42
• 어딘가에 포함되어 있는 “cat”

   bobcat, category, staccato, 123cat456 …




                              * 코드 출처:
Korean Perl Workshop 2012     한 권으로 끝내는 정규표현식, 67
                                                    43
• 어딘가에 포함되어 있는 “cat”

   bobcat, category, staccato, 123cat456 …


• 오답
   /BcatB/




Korean Perl Workshop 2012                    44
• 어딘가에 포함되어 있는 “cat”

   bobcat, category, staccato, 123cat456 …


• 오답
   /BcatB/
• 정답
   /Bcat|catB/


Korean Perl Workshop 2012                    45
• “cat”을 제외한 모든 단어
        snake, bat, dog, bobcat, …




                               * 코드 출처:
Korean Perl Workshop 2012      한 권으로 끝내는 정규표현식, 372
                                                      46
• “cat”을 제외한 모든 단어
        snake, bat, dog, bobcat, …


• 흔히 보이는 오답
   /b[^cat]+b/
    – [^…]를 단어를 배제하는 용도로 쓰면 안 됨




Korean Perl Workshop 2012            47
• “cat”을 제외한 모든 단어
        snake, bat, dog, bobcat, …


• 흔히 보이는 오답
   /b[^cat]+b/
    – [^…]를 단어를 배제하는 용도로 쓰면 안 됨
• 마찬가지
  /b[^c][^a][^t]b/



Korean Perl Workshop 2012            48
• “cat”을 제외한 모든 단어
        snake, bat, dog, bobcat, …


• 정답
  /b(?!catb)w+/




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


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




                               * 코드 출처:
Korean Perl Workshop 2012      한 권으로 끝내는 정규표현식
                                                 50
“일치하지 않음” vs “아닌 것에 일치함”
$str = 'I paid $30 for 100 apples';




                              * 코드 출처:
Korean Perl Workshop 2012     손에 잡히는 정규표현식, 93
                                                 51
$str = 'I paid $30 for 100 apples';

# 가격에만 일치
$str =~ /$d+/;




Korean Perl Workshop 2012             52
$str = 'I paid $30 for 100 apples';

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




Korean Perl Workshop 2012             53
my $str = 'I paid $30 for 100 apples';

# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색




Korean Perl Workshop 2012                54
my $str = 'I paid $30 for 100 apples';

# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색
                      # 실패




Korean Perl Workshop 2012                55
my $str = 'I paid $30 for 100 apples';

# 가격이 아닌 수량에만 일치??
$str =~ /(?<!$)d+/; # 부정형 후방탐색
                      # 실패

$str =~ /b(?<!$)d+/;     # 앵커가 필요함




Korean Perl Workshop 2012                56
전후방탐색의 활용

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


                 이 형태만 생각하기 쉬움




Korean Perl Workshop 2012                       57
일련의 숫자, 그 뒤에 일련의 문자 형태

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




Korean Perl Workshop 2012   58
• 전체 문자열이 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
• 정규식 안의 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
• 정규식과 코드의 협동

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




Korean Perl Workshop 2012   61
• 전방탐색

        /^(?=.{4,6}$)d+[a-z]+$/

        둘 이상의 조건을 동시에 검사




Korean Perl Workshop 2012          62
전방탐색과 조건식 결합
올바른 우편번호 찾기

11111            (o)
22222            (o)
33333-           (x)
44444-4444       (o)




                            * 코드 출처:
Korean Perl Workshop 2012   손에 잡히는 정규표현식, 102
                                                63
올바른 우편번호 찾기

11111            (o)
22222            (o)
33333-           (x)
44444-4444       (o)

/d{5}(-d{4})?/
세번째 문자열을 걸러내지 못함


Korean Perl Workshop 2012   64
올바른 우편번호 찾기

11111            (o)
22222            (o)
33333-           (x)
44444-4444       (o)

/d{5}(?(?=-)-d{4})/
전방탐색이 성공하면 그 뒤의 패턴도 검사


Korean Perl Workshop 2012   65
Case shifting
Q L l U u E

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

    – 정규표현식 문법이 아님




Korean Perl Workshop 2012       66
$str1 = "uhello"; # $str1 = 'Hello'
'Hello' =~ /$str1/; # 일치됨




Korean Perl Workshop 2012              67
$str1 = "uhello"; # $str1 = 'Hello'
'Hello' =~ /$str1/; # 일치됨

$str2 = 'uhello';          # $str2 = 'uhello'
'Hello' =~ /$str2/;         # 런타임 에러

        “Unrecognized escape u …”

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

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

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



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




Korean Perl Workshop 2012   70
• 묘하다

"n"   =~   qr/n/          #   일치
"n"   =~   qr/Qn/        #   불일치 (qr/n/, 'n'에 일치)
"n"   =~   qr/Un/        #   불일치! (qr/N/, Perl5.8 이하 에러)
"n"   =~   qr/ln/        #   일치!
"n"   =~   qr/Ln/        #   일치!




Korean Perl Workshop 2012                                71
• 심지어

"Qn" =~ qr/Qn/ # 불일치
"Un" =~ qr/Un/ # 불일치
"Ln" =~ qr/Ln/ # 일치




Korean Perl Workshop 2012   72
Korean Perl Workshop 2012   73
/x flag
$str = "abc - 123";

$str =~ /S+ - d+/;

아주 잘 일치함




Korean Perl Workshop 2012   74
$str = "abc - 123";

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


이것은 일치하지 않는다!


Korean Perl Workshop 2012          75
$str = "abc - 123";

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


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


Korean Perl Workshop 2012             76
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
N metacharacter
/./
임의의 캐릭터 하나
    – /s 옵션이 있을 때는 뉴라인"n"에 일치
    – 없을 때는 뉴라인에 일치하지 않음


/N/
/s 옵션에 무관하게 항상 뉴라인을 제외한
임의의 캐릭터 하나




Korean Perl Workshop 2012        78
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
# 오동작
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
Named backreferences
• 매치되는 그룹에 이름을 붙임

• 앞의 예 다시

my $a99a =
'(?<char>[a-z])(?<digit>d)g{digit}g{char}';




Korean Perl Workshop 2012                        81
• 그룹의 순서가 서로 다른 패턴을 일괄처리
$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
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
$time = '2305 GMT';
if ( $time =~
     /(?|(dd|d):(dd)|(dd)(dd))s+([A-Z]{3})/
   )
{
     print "hour = $1 minute = $2 zone = $3n";
}

(?| 후보1 | 후보2 | 후보3 | … )


Korean Perl Workshop 2012                         84
$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
• 각 후보 패턴마다 그룹의 개수가 다를 경우, 리셋 그룹
  이후 나타나는 그룹은 가장 높은 번호의 다음 번호부터
  할당

• 주의: Perl 5.14 전 버전에는 버그
    • 의도한 대로 캡처되지 않음
    • 캡처 그룹이 가장 많은 후보 패턴을 제일 먼저 적어주거나
    • 빈 그룹 ()을 넣어 모든 후보의 그룹 개수를 동일하게 만들 것




Korean Perl Workshop 2012               86
PREMATCH, MATCH, POSTMATCH
$` $&     $'

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

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




                            * 코드 출처:
Korean Perl Workshop 2012   www.effectiveperlprogramming.com
                                                               87
'My cat is Buster Bean' =~ m/Buster/;
print "I matched $&n";
    # 여기서 매치 변수를 사용해버렸기 때문에

while (<>) {
    next unless /Bean/;
    # 매치할 때마다 매번 오버헤드가 발생
}




Korean Perl Workshop 2012               88
따라서, 저 세 가지 변수는

• 전혀 사용하지 않거나

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




Korean Perl Workshop 2012     89
대신 다음 변수들을 사용

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

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




Korean Perl Workshop 2012           90
'My cat is Buster Bean' =~ m/sw+sBean/p;
    # /p 옵션 사용
say "I matched ${^MATCH}";

while (<>) {
    next unless /Bean/;     # 오버헤드 없음
}




Korean Perl Workshop 2012                     91
5.10 전 버전        - 캡처 그룹과 매칭 변수로 대체
• /pattern/      + $` 대신 /(.*?)pattern/ + $1
• /pattern/      + $& 대신 /(pattern)/    + $1
• /pattern/      + $' 대신 /pattern(.*)/ + $+

• use English qw(-no_match_vars)

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




Korean Perl Workshop 2012                      92
Possessive quantifier
'abcdZ' =~ /[a-d]+Z/;




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




Korean Perl Workshop 2012   94
'abcdZ' =~ /[a-d]+Z/;
• [a-d]+는 'abcd'까지 일치
• Z는 'Z'에 일치




Korean Perl Workshop 2012   95
'abcdZ' =~ /[a-d]+Z/;
• [a-d]+는 'abcd'까지 일치
• Z는 'Z'에 일치
• 끝~




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




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




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




Korean Perl Workshop 2012             99
'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
    – 'a'를 내어놓고 재시도




Korean Perl Workshop 2012             100
'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
    – 'a'를 내어놓고 재시도
    – 'd'를 내어놓고 재시도
    – …




Korean Perl Workshop 2012             101
'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열
• [a-d]+ 는 일단 'abcda' 에 일치
• Z가 일치될 문자열이 남아 있지 않으므로
    – 'a'를 내어놓고 재시도
    – 'd'를 내어놓고 재시도
    – …
• 'bcda'를 대상으로 처음부터 다시
    – …




Korean Perl Workshop 2012             102
'abcda' =~ /[a-d]+Z/;




Korean Perl Workshop 2012   103
;;;;;;;
그, 그만…




Korean Perl Workshop 2012   104
• 독점적인 수량자

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


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




Korean Perl Workshop 2012   105
'abcda' =~ /[a-d]++Z/;




Korean Perl Workshop 2012   106
'abcda' =~ /[a-d]++Z/;
• [a-d]++ 는 'abcda'에 일치




Korean Perl Workshop 2012   107
'abcda' =~ /[a-d]++Z/;
• [a-d]++ 는 'abcda'에 일치
• Z는 일치에 실패




Korean Perl Workshop 2012   108
'abcda' =~ /[a-d]++Z/;
• [a-d]++ 는 'abcda'에 일치
• Z는 일치에 실패
• 백트래킹하지 않고 곧바로 실패 판정




Korean Perl Workshop 2012   109
'abcda' =~ /[a-d]++Z/;
• [a-d]++ 는 'abcda'에 일치
• Z는 일치에 실패
• 백트래킹하지 않고 곧바로 실패 판정

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




Korean Perl Workshop 2012   110
Korean Perl Workshop 2012   111
• 주의

'aaaaa' =~ /a++a/;

이것은 일치하지 않는다
• a++가 'aaaaa'에 일치해버리기 때문에 뒤에 a가 일치할 문자열이 남
  지 않음
• 아무 때나 Greedy 수량자 대신 사용할 수는 없음




Korean Perl Workshop 2012               112
• 독점적 수량자를 써도 괜찮은지 판단

'aaaaa' =~ / a++ a /x;      # No
'aaaaa' =~ / a++ b /x;      # Yes




Korean Perl Workshop 2012           113
• 독점적 수량자를 써도 괜찮은지 판단

'aaaaa' =~ / a++ a /x;      # No
'aaaaa' =~ / a++ b /x;      # Yes




• 수량자가 적용되는 부분의 패턴이, 뒤에 오는 패턴과
  일치하지 않으면 괜찮음


Korean Perl Workshop 2012           114
백트래킹을 하지 않는 부분식
• 독점적 수량자의 일반형

/[a-d]++Z/

/(?>[a-d]+)Z/;



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

Korean Perl Workshop 2012           115
/r flag in substitution
$str =~ s/pattern/replacement/
• $str 의 내용을 변경
• 치환 횟수를 반환


$str =~ s/pattern/replacement/r
• $str 을 변경하지 않음
• 복제본을 만들어서 복제본을 변경
• 변경된 복제본 문자열을 반환



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


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




Korean Perl Workshop 2012              117
그게 뭐야

Korean Perl Workshop 2012           118
• 좀 더 유용한 예
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
• 좀 더 유용한 예
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
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
패턴을 정의하고 이름을 붙인 후 재사용

/^ (?&osg) * ( (?&int)(?&dec)? | (?&dec) )
      (?: [eE](?&osg)(?&int) )? $

     (?(DEFINE)
       (?<osg>[-+]?)        # 생략 가능한 부호
       (?<int>d++)         # 정수
       (?<dec>.(?&int))    # 소수부
     )/x;

Korean Perl Workshop 2012                     122
Recursive Pattern
• 부등호로 둘러싸인 문자열에 일치

        /<.*?>/ 또는 /<[^<>]>/




Korean Perl Workshop 2012      123
• 부등호로 둘러싸인 문자열에 일치

        /<.*?>/ 또는 /<[^<>]>/


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


                 /????/

Korean Perl Workshop 2012       124
• 정규식은 정규문법으로 생성되는 문자열을 표현

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


• Text::Balanced
• Regexp::Common
• Parser용 모듈들


Korean Perl Workshop 2012    125
• 재귀 패턴을 사용한 정규식

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




Korean Perl Workshop 2012   126
• 재귀 패턴을 사용한 정규식

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

중첩된 패턴 =
 < > 안에
         부등호를 제외한 것들
         또는 패턴
     이 반복
Korean Perl Workshop 2012   127
/   <                       >   /x; # 부등호 안에




Korean Perl Workshop 2012                      128
/   <                       >   /x; # 부등호 안에

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




Korean Perl Workshop 2012                      129
/   <                         >   /x; # 부등호 안에

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

/ (<         [^<>]++ | (?1)   >) /x; # 또는 패턴이




Korean Perl Workshop 2012                        130
/   <                         >   /x; # 부등호 안에

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

/ (<         [^<>]++ | (?1)   >) /x; # 또는 패턴이

/ (< (?: [^<>]++ | (?1) )* >) /x; # 반복




Korean Perl Workshop 2012                        131
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
좋죠?

Korean Perl Workshop 2012         133
그러니

Korean Perl Workshop 2012     134
호스팅 업체 분들,
      Perl 5.14 이상으로 설치 좀 굽신굽신

Korean Perl Workshop 2012        135
자잘한 팁들




Korean Perl Workshop 2012   136
빈 패턴은 항상 일치
/()/
언제나 일치하며, 캡처됨

/(?!)/
언제나 실패하는 패턴




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

        … word1 … word3 … … … word2 …
        (8단어 이내에 세 단어 존재)




                             * 코드 출처:
Korean Perl Workshop 2012    한 권으로 끝내는 정규표현식
                                               138
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}
123
/x




Korean Perl Workshop 2012                         139
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}
123
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         140
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}
123
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         141
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}
123
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         142
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}                     이제부터는 아무 단어나 일치 가능
123
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         143
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8} 최대 8번까지 단어들을 일치시킨 후
123
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         144
… word1 … word3 … … … word2 …
/
b
(?:
   (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*?
){3,8}
123 전체 패턴이 일치하기 위해서는 여기를 통과해야 함
         즉 word1, word2, word3 이 한번씩 일치되었어야 함
/x
일단 word1 이 일치하면 ()가 같이 일치하고
1은 그때부터 일치


Korean Perl Workshop 2012                         145
Korean Perl Workshop 2012   146
정규식으로만 해결하려 하지 말자
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
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
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
grep
grep 'd{4}s+' file1 file2

백슬래시 쓰느라 지겨우시죠?




Korean Perl Workshop 2012        150
grep 'd{4}s+' file1 file2

grep -P 'd{4}s+' file1 file2

Perl 정규식을 사용 가능




Korean Perl Workshop 2012        151
vim
/(a|b)+

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

/v(a|b)+

Korean Perl Workshop 2012   152
• vim의 Lookaround
   – @= @!     Lookahead
   – @<= @<!   Lookbehind

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


:help pattern
:help perl-patterns

Korean Perl Workshop 2012     153
Regexp::Debugger
• Damian Conway
• CPAN



use Regexp::Debugger;
 또는
$ rxrx




Korean Perl Workshop 2012   154
"감사합니다" =~
                  /(Q(&A)?)*/


Korean Perl Workshop 2012       155

More Related Content

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

  • 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
  • 59. • 전체 문자열이 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
  • 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
  • 67. $str1 = "uhello"; # $str1 = 'Hello' 'Hello' =~ /$str1/; # 일치됨 Korean Perl Workshop 2012 67
  • 68. $str1 = "uhello"; # $str1 = 'Hello' 'Hello' =~ /$str1/; # 일치됨 $str2 = 'uhello'; # $str2 = 'uhello' 'Hello' =~ /$str2/; # 런타임 에러 “Unrecognized escape u …” • 사용자 입력을 받은 경우도 마찬가지 Korean Perl Workshop 2012 68
  • 69. • 쌍따옴표 문자열 내에 적용되는 순서 – 변수 치환 – 이스케이프, 논리 캐릭터 – Case shift $ perl -e 'print "QP*rln"' P*rl <- (n 있음) Korean Perl Workshop 2012 69
  • 70. • 정규표현식에 적용되는 순서 – 변수 치환 – Case shift – 이스케이프, 논리 캐릭터 Korean Perl Workshop 2012 70
  • 71. • 묘하다 "n" =~ qr/n/ # 일치 "n" =~ qr/Qn/ # 불일치 (qr/n/, 'n'에 일치) "n" =~ qr/Un/ # 불일치! (qr/N/, Perl5.8 이하 에러) "n" =~ qr/ln/ # 일치! "n" =~ qr/Ln/ # 일치! Korean Perl Workshop 2012 71
  • 72. • 심지어 "Qn" =~ qr/Qn/ # 불일치 "Un" =~ qr/Un/ # 불일치 "Ln" =~ qr/Ln/ # 일치 Korean Perl Workshop 2012 72
  • 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
  • 84. $time = '2305 GMT'; if ( $time =~ /(?|(dd|d):(dd)|(dd)(dd))s+([A-Z]{3})/ ) { print "hour = $1 minute = $2 zone = $3n"; } (?| 후보1 | 후보2 | 후보3 | … ) Korean Perl Workshop 2012 84
  • 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
  • 93. Possessive quantifier 'abcdZ' =~ /[a-d]+Z/; Korean Perl Workshop 2012 93
  • 94. 'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치 Korean Perl Workshop 2012 94
  • 95. 'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치 • Z는 'Z'에 일치 Korean Perl Workshop 2012 95
  • 96. 'abcdZ' =~ /[a-d]+Z/; • [a-d]+는 'abcd'까지 일치 • Z는 'Z'에 일치 • 끝~ Korean Perl Workshop 2012 96
  • 97. 'abcda' =~ /[a-d]+Z/; # 일치하지 않는 문자열 Korean Perl Workshop 2012 97
  • 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
  • 103. 'abcda' =~ /[a-d]+Z/; Korean Perl Workshop 2012 103
  • 105. • 독점적인 수량자 ?+ *+ ++ {2,5}+ • 일치에 성공한 부분은 백트래킹하지 않음 Korean Perl Workshop 2012 105
  • 106. 'abcda' =~ /[a-d]++Z/; Korean Perl Workshop 2012 106
  • 107. 'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치 Korean Perl Workshop 2012 107
  • 108. 'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치 • Z는 일치에 실패 Korean Perl Workshop 2012 108
  • 109. 'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치 • Z는 일치에 실패 • 백트래킹하지 않고 곧바로 실패 판정 Korean Perl Workshop 2012 109
  • 110. 'abcda' =~ /[a-d]++Z/; • [a-d]++ 는 'abcda'에 일치 • Z는 일치에 실패 • 백트래킹하지 않고 곧바로 실패 판정 • 단, 여기서 끝은 아님 – 문자열의 다음 위치에서 재시도 Korean Perl Workshop 2012 110
  • 111. Korean Perl Workshop 2012 111
  • 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
  • 118. 그게 뭐야 Korean Perl Workshop 2012 118
  • 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
  • 123. Recursive Pattern • 부등호로 둘러싸인 문자열에 일치 /<.*?>/ 또는 /<[^<>]>/ Korean Perl Workshop 2012 123
  • 124. • 부등호로 둘러싸인 문자열에 일치 /<.*?>/ 또는 /<[^<>]>/ • 중첩된 형태에도 일치 "< … < … > … < … < … > > … >" /????/ Korean Perl Workshop 2012 124
  • 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
  • 131. / < > /x; # 부등호 안에 / < [^<>]++ > /x; # 부등호 외의 것들 / (< [^<>]++ | (?1) >) /x; # 또는 패턴이 / (< (?: [^<>]++ | (?1) )* >) /x; # 반복 Korean Perl Workshop 2012 131
  • 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
  • 135. 호스팅 업체 분들, Perl 5.14 이상으로 설치 좀 굽신굽신 Korean Perl Workshop 2012 135
  • 136. 자잘한 팁들 Korean Perl Workshop 2012 136
  • 137. 빈 패턴은 항상 일치 /()/ 언제나 일치하며, 캡처됨 /(?!)/ 언제나 실패하는 패턴 Korean Perl Workshop 2012 137
  • 138. • 세 단어가 순서 무관하게 가까이 붙어 있는 경우를 검색 … word1 … word3 … … … word2 … (8단어 이내에 세 단어 존재) * 코드 출처: Korean Perl Workshop 2012 한 권으로 끝내는 정규표현식 138
  • 139. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 123 /x Korean Perl Workshop 2012 139
  • 140. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 123 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 140
  • 141. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 123 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 141
  • 142. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 123 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 142
  • 143. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 이제부터는 아무 단어나 일치 가능 123 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 143
  • 144. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 최대 8번까지 단어들을 일치시킨 후 123 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 144
  • 145. … word1 … word3 … … … word2 … / b (?: (?>word1()|word2()|word3()|(?>1|2|3)w+)bW*? ){3,8} 123 전체 패턴이 일치하기 위해서는 여기를 통과해야 함 즉 word1, word2, word3 이 한번씩 일치되었어야 함 /x 일단 word1 이 일치하면 ()가 같이 일치하고 1은 그때부터 일치 Korean Perl Workshop 2012 145
  • 146. Korean Perl Workshop 2012 146
  • 147. 정규식으로만 해결하려 하지 말자 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
  • 148. 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
  • 149. 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
  • 150. grep grep 'd{4}s+' file1 file2 백슬래시 쓰느라 지겨우시죠? Korean Perl Workshop 2012 150
  • 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
  • 154. Regexp::Debugger • Damian Conway • CPAN use Regexp::Debugger; 또는 $ rxrx Korean Perl Workshop 2012 154
  • 155. "감사합니다" =~ /(Q(&A)?)*/ Korean Perl Workshop 2012 155