DATA 전문가로 가는 길

[Perl] 정규표현식 본문

Programming/Perl

[Perl] 정규표현식

EstenPark 2009. 4. 24. 22:18

1. 정규표현식이란 ?
아래 사이트 즉 google + search
http://www.google.co.kr/search?complete=1&hl=ko&newwindow=1&q=perl+정규표현식&lr=&aq=f&oq
흔히 말하는 grep, egrep 보다 더 많은 정규표현식을 가지고 있는 perl로 문서를 작성 하도록 할 것 입니다.

2. 정규표현식의 기초
기본적으로 사용되는 3가지

  • 문자에 해당되는 부분
  • 앞의 해당되는 부분을 반복하는 부분
  • 문자에 해당되지 않고 위치나 결합을 나타내는 부분

3. Perl 정규표현식

3-1 기본적인 대입

pubuntu@pubuntu:~$ perl -e 'print "Perl Love" =~ /Love/ ."\n"'
1
pubuntu@pubuntu:~$ perl -e 'print "Perl Love" !~ /love/ ."\n"'
1

  • pattern match 관련하여 연산하는 방법은 (=~, !~) 좌측과 대입하는 연산자
  • "Perl Love" 문자열과 대입하여 참인 결과를 얻기 위해서는 [=~ /Love/] 나 [!~ /love]로 대입
  • =~ 결과에 대한 참, 거짓 (같다), !~ 결과에 대한 참, 거짓 (같지않다) 일동 단결


pubuntu@pubuntu:~$ perl -e 'print "Perl Love" =~ /love/ ."\n"'

pubuntu@pubuntu:~$ perl -e 'print "Perl Love" !~ /Love/ ."\n"'

  • "Perl Love" 문자열과 대입하여 거짓인 결과를 얻기 위해서는 [=~ /love/] 나 [!~ /Love/] 로 대입

 
use strict;
use warnings;


my $regexp = "Mass";

if ("estenpark" =~ /$regexp/) {
	print "True \n";
} else {
	print "Fail \n";
}

  • 스칼라 변수를 정규표현식에 대입 하는 방법
  • $regexp 변수의 값은 "Mass"이며, 대입 할 값은 "estenpark" 색칠 한 부분에 적용
  • 대소문자 구분없이 하고 싶다면 " /pattern/i  " i 옵션을 이용하여 대소문자 관계 없이 매치


 4-1 본론

__DATA__
-------------------------------------------------------------------
2009/04/23-10:23:34:45 MSG=[PERL0001] CODE=[0002]
-------------------------------------------------------------------
2009/04/23-10:24:34:45 MSG=[PERL0002] CODE=[0001]
-------------------------------------------------------------------
2009/04/24-10:25:34:45 MSG=[PERL0003] CODE=[0001]
-------------------------------------------------------------------
2009/04/24-10:26:34:45 MSG=[PERL0004] CODE=[0002]
-------------------------------------------------------------------
2009/04/24-10:27:34:45 MSG=[PERL0005] CODE=[0002]
-------------------------------------------------------------------

  • Anchors
    • ^ : 줄의 시작    ( ABCDE )
    • $ : 줄의 마지막 ( ABCDE )
  • Common Character Class
    • \d : [0-9]
    • \D : negated \d [^0-9]
    • \s : whitespace  [\ \t\r\n\f]
    • \S : negated \s [^\s]
    • \w : word character [0-9a-zA-Z_]
    • \W : negated \w [^\w]
  • Metacharacters
    • {} : {n,m}, {m,}, {n} Maximal Match 일치하는 가장 긴 스트링
    • [] : [문자] -> [ABCD] : A,B,C,D 각각의 문자로 매치
    • () : (pattern) -> (?#문자) : #주석, (?[=|!]x)위치에 놓일 문자열 매치(된다/안된다), (x) 뒤에 참조
    • \1: (문자열) -> /(ABC)-\1/ : 첫번째 참조 문자열 대입 즉, ABC-ABC
    •  | : [문자or문자열 | 문자 or 문자열] -> [perl|love] : perl과 love에 매치
    •  - : [1-3] : 사각 괄호 안에서 대시 문자는 문자 범위를 지정 즉, 123 
    •  * : x* : x가 0번 이상 반복 되는 문자열
    •  + : x+ : x가 1번 이상 반복 되는 문자열
    •  ? : x? : x가 나오지 않거나 1번 나오는 경우
    • \ : \$ -> [\$str\[\^] : 역슬래시는 직후에 오는 특수 문자를 일반 문자로 취급
    •  .  : New Line을 제외한 모두
  • Match, Substitute, Translate
    • m : m!pettern!, m@pettern@ -> 구분자를 변경 (기본 /)
    • s  : s// -> substring을 치환
    • t   : tr// ->  각 글자를 해석
  • Modifier
    • g : global, 문장 내에서 여러번 match가 일어날 때마다
    • i  : case-insensitive, 대소문자 구분없이
    • m : multiple-line, 여러 line을 한꺼번에 사용함
    • o :  comple once, compile시에 pattern을 딱 한번 해석함
    • s : single-line, string을 한 line으로 가정함
    • v : Extended Regular Experssion 을 사용함

 

Q1. 시작이 숫자로 시작 하는 라인을 출력 


foreach
my $list (<DATA>) {
    if ($list =~ /^\d/ ) {
        print $list;
   }
}
결과
2009/04/24-10:23:34:45 MSG=[PERL0001] CODE=[0002]
2009/04/24-10:24:34:45 MSG=[PERL0002] CODE=[0001]
2009/04/24-10:25:34:45 MSG=[PERL0003] CODE=[0001]
2009/04/24-10:26:34:45 MSG=[PERL0004] CODE=[0002]
2009/04/24-10:27:34:45 MSG=[PERL0005] CODE=[0002]

  • \d를 이용하여 숫자를 찾고 ^로 매치하여 시작이 숫자인 것만 출력
  • if ($list =~ m@^\d{4}/\d{2}/\d{2}@ ) {} 기본적으로 perl 에서는 / / 매치 된느데 이것을 m/ /을 이용하여 m@pattern@ 사용

Q2. "CODE=[0001]" 의 라인을 출력

foreach my $list (<DATA>) {
    if ($list =~ /CODE\=\[\d\d\d1\]/ ) {
  print $list;
    }
}

결과
2009/04/24-10:24:34:45 MSG=[PERL0002] CODE=[0001]
2009/04/24-10:25:34:45 MSG=[PERL0003] CODE=[0001]

  • \를 이용하여 =,[,]을 문자열로 인식 시켜 놓고 숫자 3자리다음 1이 오는 라인을 출력
  • if ($list =~ /CODE\=\[\d{3}1\]/ ) { } 매치 숫자3자리가 중복으로 반복 된다면 \d{3} 으로 매치
  • if ($list =~ /CODE.+1/ ) { } .(NewLine을 제외 한)을 사용하여 1번이상 반복 되고 마지막에 1을 매치

Q3. 2009/04/23 이면서 MSG=[PERL0001]인 라인을 출력

foreach my $list (<DATA>) {
    if ($list =~ m@2009/04/23(.*)MSG\=\[PERL0001\]@ ) {
        print $list;
    }
}

결과
2009/04/23-10:23:34:45 MSG=[PERL0001] CODE=[0002]

  • m을 사용하여 구분자를 변경 할 수 있으므로 / /를 m @ @로 변경하여 원하는 값을 출력 
  • 2009/04/23(.*)는 2009/04/23이후 \n이 아닌 모든 문자를 매치
  • MSG\=\[PERL0001\] \(역슬래시)를 이용하여 =[]를 문자로 매치 후 PERL0001을 출력

Q4. MSG=[PERL0001] 에서 PERL0002~0003만 출력

foreach my $list (<DATA>) {
    if ($list =~ /MSG\=\[PERL000[2-3]/ ) {
        print $list;
    }
}

결과
2009/04/23-10:24:34:45 MSG=[PERL0002] CODE=[0001]
2009/04/24-10:25:34:45 MSG=[PERL0003] CODE=[0001]

  • /MSG\=\[PERL000[2-3]/   - 범위 연산자를 이용하여 0002와 0003을 출력
  • /MSG\=\[PERL000[23]/   위와 같은 의미를 같고 있지만 특별한 경우 아니면 - 범위 연산자 사용


Comments