· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
perldoc/perlrequick


1. 번역문서정보

1.1. 원저자 및 번역자

원저자 : Mark Kvale
번역자 : redneval@kldp.org

1.2. 영문원본 출처

링크 : http://perldoc.perl.org/perlrequick.html
분류 및 이름 : Perl 5.8.8 documentation - Tutorials - perlrequick

1.3. 저작권 및 라이센스

본 번역문서의 번역부분에 해당되는 부분의 원 저작권은 redneval@kldp.org 에 있다. 다만, 저작권에 따른 모든 권리는 Free Software Foundation (FSF) 로 이양한다.

본 번역문서는 영문 perlrequick의 라이센스에 따라 GPL을 따른다. 그러므로, 본 번역문서의 GPL버전은 영문 perlrequick의 GPL버전을 따른다. 만약, 영문 perlrequick의 GPL버전이 바뀌면, 본 번역문서 또한 그 바뀐 버전으로 바꿔서 사용할 수 있다.

1.4. 링크

펄에 관한 다른 문서를 보고 싶다면 perldoc을 참고하라.

2. 번역문서

2.1. 이름

perlrequick - 펄 정규표현식 빠르게 시작하기

2.2. 설명

본 페이지는, 펄에서 정규표현식을 이해하고 작성하고 사용하는데 필요한 가장 기초적인 내용을 다룬다.


2.2.1. 단어설명

  • 매치(match): proper한 한글 대역어를 찾을 수 없었다.
  • 구분자(delimiter)
  • 메타문자(metacharacter)
  • escaped character: 한글 대역어에 대해 논란이 있다. http://kldp.org/node/76662
  • anchor 메타문자, 단어 anchor: anchor의 뜻은 닻이다. ^, $, \b가 마치 배의 닻과 같이 위치를 고정시켜준다는 의미이다.
  • 수식어(modifier): '변경자'로 번역할 수 있지만, 펄의 문학적 특성을 고려하여 '수식어'로 번역하였다. 마찬가지 이유로 '수량형용사(quantifier)'는 '수량지시자'로 번역하지 않겠다.
  • double quoted 문자열, single quoted 문자열: FIX_ME

2.2.2. 단순 단어 매치

정규표현식에서 가장 간단한 경우는 단순한 단어 또는 문자열을 찾는 경우이다. 단어 하나로 구성된 정규표현식은, 그 단어를 포함한 모든 문자열에 대해서 매치된다.

    "Hello World" =~ /World/;  # matches

이 실행문에서 "World"는 정규표현식이고, "/World/"는 "World"를 포함한 문자열을 찾으라는 것을 의미한다. =~ 연산자는 정규표현식과 // 연산자와 함께 작용하여, 좌변의 문자열이 정규표현식에 매치되면 참값을 반환하게 된다. 만약 매치가 되지 않으면 거짓값을 반환하게 된다. 위의 경우에는 "World"문자열은 "Hello World"문자열에 존재하므로 위의 표현식은 참값을 갖는다. 이를 응용하여 다음과 같이 할 수 있다.

첫번째로는, 다음과 같이 조건문으로 사용할 수 잇다.

    print "It matches\n" if "Hello World" =~ /World/;

!~ 연산자는 =~ 연산자의 반대의미로 사용된다.

    print "It doesn't match\n" if "Hello World" !~ /World/;
정규표현식의 일부로 변수를 사용할 수도 있다.

    $greeting = "World";
    print "It matches\n" if "Hello World" =~ /$greeting/;

만약 $_에 대해서 매치하는 경우는 "$_ =~" 부분을 생략할 수 있다.

    $_ = "Hello World";
    print "It matches\n" if /World/;

마지막으로, 기본 구분자로 사용되는 //대신에 다른 임의의 문자를 사용할 수 있다. 이 경우는 앞에 'm'을 붙여줘야 한다.

    "Hello World" =~ m!World!;   # matches, delimited by '!'
    "Hello World" =~ m{World};   # matches, note the matching '{}'
    "/usr/bin/perl" =~ m"/perl"; # matches after '/usr/bin',
                                 # '/' becomes an ordinary char

참값을 가지려면, 정규표현식이 문자열의 일부와 정확히 일치해야한다.

    "Hello World" =~ /world/;  # 기본적으로 정규표현식은 대소문자를 구분하므로, 이 경우는 매치되지 않는다.

    "Hello World" =~ /o W/;    # 공백문자 ' '도 또한 문자로 취급되므로, 이 경우는 매치된다.

    "Hello World" =~ /World /; # "Hello World"의 끝에 공백문자 ' '가 없으므로 매치되지 않는다.

정규식은 매치 가능한 가장 앞부분에서 매치된다.

    "Hello World" =~ /o/;       # matches 'o' in 'Hello'
    "That hat is red" =~ /hat/; # matches 'hat' in 'That'

모든 문자가 문자그대로의 매치로 사용되는 것은 아니다. 메타문자라고 불리는 몇몇 문자들은 정규표현식의 특수구문을 위해 사용된다. 메타문자는

    {}[]()^$.|*+?\
이 있으며, 역슬래쉬 '\' 뒤에 쓰게 되면 문자그대로의 매치에 사용할 수 있다.

    "2+2=4" =~ /2+2/;    # doesn't match, + is a metacharacter
    "2+2=4" =~ /2\+2/;   # matches, \+ is treated like an ordinary +
    'C:\WIN32' =~ /C:\\WIN/;                       # matches
    "/usr/bin/perl" =~ /\/usr\/bin\/perl/;  # matches

위의 마지막 정규표현식을 보면, 슬래쉬 '/' 앞에도 역슬래쉬를 붙여줘야 하는데, 그 이유는 슬래쉬 문자가 정규표현식의 구분자로 사용됐기 때문이다.

ASCII문자 중에서 escaped character라고 불리는 문자들은 '\' 문자를 사용하여 나타낼 수 있다. 예를 들면, 탭문자는 \t, 줄바꿈을 위해 사용되는 newline과 carriage return은 각각 \n 와 \r 로 나타낼 수 있다. \로 시작하는 숫자는 8진수를 나타내고, \x로 시작하면 16진수를 나타낼 수 있다. (예를 들면, \033 은 8진수 33이고 \x1B 는 16진수 1B이다.)

    "1000\t2000" =~ m(0\t2)        # matches
    "cat"        =~ /\143\x61\x74/ # matches, but a weird way to spell cat

정규표현식은 일반적인 double quoted 문자열과 마찬가지로 취급된다. 그러므로 정규표현식의 일부로 변수를 사용하는 것이 가능하다.

    $foo = 'house';
    'cathouse' =~ /cat$foo/;   # matches
    'housecat' =~ /${foo}cat/; # matches

위에서 살펴본 모든 정규표현식들을 살펴보면, 정규표현식은 문자열의 위치에 상관없이 매치됨을 알 수 있다. 위치를 지정하기 위해서 anchor 메타문자를 사용할 수 있다. ^ 는 문자열의 처음을 지정하고, $ 는 문자열의 끝 또는 \n문자의 바로 앞을 지정한다.

    "housekeeper" =~ /keeper/;         # matches
    "housekeeper" =~ /^keeper/;        # doesn't match
    "housekeeper" =~ /keeper$/;        # matches
    "housekeeper\n" =~ /keeper$/;      # matches
    "housekeeper" =~ /^housekeeper$/;  # matches


2.2.3. 문자 집합

정규표현식의 한 부분을 표현하는데 있어서, 하나의 문자를 사용하는 것 대신에, 매치 가능한 문자들을 나열하는 방식으로 문자 집합을 사용할 수 있다. 나열된 문자들을 대괄호로 둘러싸는 것으로 문자 집합임을 나타낸다. 다음의 예를 보자.

    /cat/;            # matches 'cat'
    /[bcr]at/;        # matches 'bat', 'cat', or 'rat'
    "abc" =~ /[cab]/; # matches 'a'

마지막 실행문을 살펴보자. 정규표현식 상의 문자 집합의 첫번째 문자는 'c' 였음에도, 정규표현식이 매치하는 것은 'c'가 아닌 'a'가 된다.

    /[yY][eE][sS]/; # match 'yes' in a case-insensitive way
                    # 'yes', 'Yes', 'YES', etc.
    /yes/i;         # also match 'yes' in a case-insensitive way

마지막에 든 예에서는, 수식어 'i'를 사용함으로써 대소문자 구분을 하지 않도록 만들었다.

문자 집합 내에서 문자를 쓸 때도 역시 특수문자는 앞에서 언급한 방식으로 사용해야 한다. 그런데 문자 집합 내에서는 추가적으로 -]\^$ 가 특수문자가 되므로 이를 사용하기 위해서는 역슬래쉬를 앞에 붙여야 한다.

   /[\]c]def/; # matches ']def' or 'cdef'
   $x = 'bcr';
   /[$x]at/;   # matches 'bat, 'cat', or 'rat'
   /[\$x]at/;  # matches '$at' or 'xat'
   /[\\$x]at/; # matches '\at', 'bat, 'cat', or 'rat'

문자 집합 내의 특수문자 '-'는 범위 연산자처럼 작용한다. 그러므로 단순한 방식인 `0123456789``abc...xyz` 대신에, 우아한 방식인 <0-9><a-z> 을 사용할 수 있다.

    /item[0-9]/;  # matches 'item0' or ... or 'item9'
    /[0-9a-fA-F]/;  # matches a hexadecimal digit

만약 '-'문자가 문자 집합의 첫 문자나 마지막 문자로 사용되면, 특수문자가 아닌 문자그대로의 의미를 갖는다.

문자 집합의 첫번째 위치에 '^'문자가 있으면 이는 특수문자이며, 이는 문자 집합에 반대의 의미를 갖게 한다. 즉, 문자 집합내에 없는 모든 문자를 매치한다. `...``^...`는 둘 다 하나의 문자에 매치되며, 그렇지 않으면 매치는 실패한다.

    /[^a]at/;  # doesn't match 'aat' or 'at', but matches
               # all other 'bat', 'cat, '0at', '%at', etc.
    /[^0-9]/;  # matches a non-numeric character
    /[a^]at/;  # matches 'aat' or '^at'; here '^' is ordinary

펄은 일반적으로 많이 쓰이는 몇가지 문자 집합에 대해서 약어를 가지고 있다.

  • \d 는 숫자를 나타낸다. 즉, 다음과 같다.
  • \d
    [0-9]
  • \s 는 공백문자를 나타낸다.
    [\ \t\r\n\f]
  • \w 는 '_'와 알파벳을 나타낸다.
    [0-9a-zA-Z_]
  • \D 는 \d 의 반대이다.
    [^0-9]
  • \S 는 \s 의 반대이다.
    [^\s]
  • \W 는 \w 의 반대이다.
    [^\w]
  • 마침표 '.' 는 "\n"를 제외한 모든 문자에 매치된다.

약어 \d\s\w\D\S\W 는 문자집합 안과 밖에서 쓰일 수 있다.

    /\d\d:\d\d:\d\d/; # matches a hh:mm:ss time format
    /[\d\s]/;         # matches any digit or whitespace character
    /\w\W\w/;         # matches a word char, followed by a
                      # non-word char, followed by a word char
    /..rt/;           # matches any two chars, followed by 'rt'
    /end\./;          # matches 'end.'
    /end[.]/;         # same thing, matches 'end.'

단어 anchor \b는 \w와 \W의 경계에 매치된다. (즉, 단어의 경계에 매치된다.)

    $x = "Housecat catenates house and cat";
    $x =~ /\bcat/;  # matches cat in 'catenates'
    $x =~ /cat\b/;  # matches cat in 'housecat'
    $x =~ /\bcat\b/;  # matches 'cat' at end of string

마지막 예에서 보면, 문자열의 끝 또한 단어의 경계로 간주되는 것을 알 수 있다.


2.2.4. 메타문자 '|'

앞에서는 문자 집합을 다뤘는데, 이번에는 문자열에 대해서 비슷하게, 하나의 문자열 대신에 매치 가능한 문자열(후보라고 부르겠다.)을 나열하는 방식을 사용할 수 있다. 예를 들어 dog 또는 cat 을 매치하고 싶다면 정규표현식 dog|cat 를 사용할 수 있다. 후보 중에서 먼저 있는 후보를 우선적으로 매치하게 된다. 즉, dog가 매치되지 않은 경우에 그 다음 후보인 cat가 매치되는지를 살피게 된다. 만약 cat도 매치가 되지 않으면, 매치는 실패하고 문자열의 다음 위치에서 다시 매치를 시도한다. 예를 한 번 보자.

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

두번째 정규표현식을 보자. dog가 첫번째 후보 이기는 하지만, 문자열 "cats and dogs"에 대해서는 cat가 먼저 매치되게 된다.

    "cats"          =~ /c|ca|cat|cats/; # matches "c"
    "cats"          =~ /cats|cat|ca|c/; # matches "cats"

매치되는 문자열의 위치가 같은 경우는 앞에 있는 후보가 우선적으로 매치된다. 그러므로 위의 예와같이 모든 후보가 매치되는 경우에는 첫번째 후보가 매치된다.


2.2.5. 그룹과 중첩구조

그룹 메타문자인 ()는 정규표현식의 일부분을 하나의 유닛으로 다루게 해준다. 이를 "그룹으로 만든다"고 하며, 정규표현식에서 ()으로 둘러쌈으로써 할 수 있다. 예를 들어, house(cat|keeper)는 house뒤에 cat 또는 keeper가 오는 문자열을 매치한다.

    /(a|b)b/;    # matches 'ab' or 'bb'
    /(^a|b)c/;   # matches 'ac' at start of string or 'bc' anywhere
  
    /house(cat|)/;  # matches either 'housecat' or 'house'
    /house(cat(s|)|)/;  # matches either 'housecats' or 'housecat' or
                        # 'house'.  Note groups can be nested.

    "20" =~ /(19|20|)\d\d/;  # matches the null alternative '()\d\d',
                             # because '20\d\d' can't match


2.2.6. 매치된 문자열에서 추출하기

그룹 메타문자 ()를 이용하면 매치된 문자열에서 추출하는 것이 가능하다. 각각의 그룹에 매치된 문자열들은 특수변수 $1, $2, ... 등으로 순서대로 저장된다. 이 특수변수들은 다른 일반 변수과 같은 방식으로 사용할 수 있다.

    # extract hours, minutes, seconds
    $time =~ /(\d\d):(\d\d):(\d\d)/;  # match hh:mm:ss format
    $hours = $1;
    $minutes = $2;
    $seconds = $3;

그룹이 사용된 정규표현식 /regex/은, 리스트로 다뤄질 경우에 ($1,$2,...) 의 값을 반환하게 된다. 그러므로 위의 예제는 다음과 같이 바꿔쓸 수 있다.

    ($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/);

만약 정규표현식이 중첩되는 경우, $1은 가장 왼쪽의 ( 문자로 지정된 그룹, $2는 두 번재로 왼쪽에 위치한 ( 문자로 지정된 그룹에 의해 문자열이 저장되게 된다. 예를 들어, 다음과 같이 정규표현식이 있을 때 각각의 그룹에 할당되는 특수변수의 번호는 그 아래에 적어 놓았다.

    /(ab(cd|ef)((gi)|j))/;
     1  2      34

'역참조자'로 불리는 \1 , \2 , ... 들은, 정규표현식 내에서 $1 , $2 , ... 과 같은 역할을 하게 된다.

    /(\w\w\w)\s\1/; # find sequences like 'the the' in string

$1 , $2 , ... 는 정규표현식의 밖에서만 쓰여야 하고, \1 , \2 , ... 는 정규표현식 안에서만 쓰여야 한다.


2.2.7. 반복 매치

정규표현식의 한 부분을 원하는 수만큼 반복하기 위해서, 수량 메타문자(또는 수량형용사) ?, * , + , {} 를 사용할 수 있다. 수량형용사는 문자, 문자 집합, 그룹의 바로 뒤에 올 수 있다. 그들의 의미는 다음과 같다.

  • a{n,m} : 최소 n번이상 최대 m번이하 매치한다.
  • a{n,} : 최소 n번이상 매치한다.
  • a{n} : 정확히 n번 매치한다.
  • a? : a{0,1} 와 같다.
  • a* : a{0,} 와 같다.
  • a+ : a{1,} 와 같다.

예를 한번 보자.

    /[a-z]+\s+\d*/;  # match a lowercase word, at least some space, and
                     # any number of digits
    /(\w+)\s+\1/;    # match doubled words of arbitrary length
    $year =~ /\d{2,4}/;  # make sure year is at least 2 but not more
                         # than 4 digits
    $year =~ /\d{4}|\d{2}/;    # better match; throw out 3 digit dates

수량형용사는 매치될 수 있는한 최대한 많은 횟수를 매치하는 방식으로 작동한다. 그러므로,

    $x = 'the cat in the hat';
    $x =~ /^(.*)(at)(.*)$/; # matches,
                            # $1 = 'the cat in the h'
                            # $2 = 'at'
                            # $3 = ''   (0 matches)

첫번째 수량형용사가 있는 (.*) 부분은 최대한 많은 문자열을 가지려고 하기 때문에 'the c'에서 매치되고 끝나는 것이 아니라 'the cat in the h'까지 매치된다. 그러므로 두번째 (.*)부분은 아무런 문자열도 가지지 못한다. 즉, 0번 매치된다.

매치 연산자에 대해 알아야할 사항이 몇 가지 더 있는데,

    $pattern = 'Seuss';
    while (<>) {
        print if /$pattern/;
    }

위의 코드에서 매 루프마다 $pattern이 재계산된다. 만약 $pattern값이 안 바뀌어서 재계산이 필요없다면, //o 수식어를 사용하라. 이 경우 $pattern은 한번만 대입된다. 만약 변수가 대입되는 것을 막고 싶다면, 특수 구분자 m'' 을 사용하라. 그러면 이를 문자 그대로 해석하게 된다.

    @pattern = ('Seuss');
    m/@pattern/; # matches 'Seuss'
    m'@pattern'; # matches the literal string '@pattern'

전역 수식어 //g를 사용하면 원하는 만큼 많은 횟수를 매치할 수 있다. 그런 식으로 연속적으로 매치가 이뤄지면, 매치가 한 번씩 이뤄질 때마다, 매치 포인트가 다음 위치로 이동하게 된다. 만약 이 위치들을 알고 싶다면 pos() 함수를 사용하면 된다. 예를들어

    $x = "cat dog house"; # 3 words
    while ($x =~ /(\w+)/g) {
        print "Word is $1, ends at position ", pos $x, "\n";
    }

위의 코드는 다음과 같은 출력결과를 얻는다.

    Word is cat, ends at position 3
    Word is dog, ends at position 7
    Word is house, ends at position 13

매치가 실패하거나 정규표현식 연산을 다른 문자열에 적용하는 경우, pos함수에 의한 값은 초기화가 된다. 매치가 실패할 때 초기화되는 것을 막으려면 //c 수식어를 사용하면 된다. 예를 들면, /regex/gc 로 사용할 수 있다.

//g 연산자를 리스트로 다루면, //g 는 매치된 그룹의 리스트를 반환한다. 만약 그룹이 하나도 없다면, 정규표현식 전체에 의해 매치된 부분의 리스트를 반환한다.

    @words = ($x =~ /(\w+)/g);  # matches,
                                # $word[0] = 'cat'
                                # $word[1] = 'dog'
                                # $word[2] = 'house'


2.2.8. 찾아바꾸기

찾아바꾸기는 s/regex/replacement/modifiers 와 같은식으로 사용할 수 있다. replacement는 펄의 문자열을 쓰면 된다. 정규표현식에 의해 매치된 부분은 replacement로 대체된다. =~ 연산자도 또한 사용할 수 있다. 마찬가지로 $_에 대해 매치하는 경우 "$_ =~" 를 생략할 수 있다. 매치된 부분이 있다면, s///는 매치된 횟수를 반환하게 된다. 매치된 부분이 없다면 거짓값을 반환한다. 다음 예를 살펴보자.

    $x = "Time to feed the cat!";
    $x =~ s/cat/hacker/;   # $x contains "Time to feed the hacker!"
    $y = "'quoted words'";
    $y =~ s/^'(.*)'$/$1/;  # strip single quotes,
                           # $y contains "quoted words"

s/// 연산자를 사용할 때는, 매치된 변수들인 $1 , $2 등은 replacement 위치에서 사용할 수 있다. 전역 수식어를 같이 쓰면, s///g 연산자는 매치가 되는한 찾아바꾸기를 계속하여 실행한다.

    $x = "I batted 4 for 4";
    $x =~ s/4/four/;   # $x contains "I batted four for 4"
    $x = "I batted 4 for 4";
    $x =~ s/4/four/g;  # $x contains "I batted four for four"

계산 수식어를 사용한 s///e 연산자는 replacement를 문자그대로 해석하지 않고, 수식으로 보고 계산을 한 뒤에 그 값을 사용한다. 이는 replacement 부분을 eval{...} 함수를 이용하여 계산하는 것으로 볼 수 있다.

    # reverse all the words in a string
    $x = "the cat in the hat";
    $x =~ s/(\w+)/reverse $1/ge;   # $x contains "eht tac ni eht tah"

    # convert percentage to decimal
    $x = "A 39% hit rate";
    $x =~ s!(\d+)%!$1/100!e;       # $x contains "A 0.39 hit rate"

마지막 예를 보자. m//의 경우와 같이 s/// 또한 구분자로 다른 문자를 사용할 수 있다. 예를 들어 s!!! , s{}{}, 심지어는 s{}// 로 쓸 수도 있다. 만약 s''' 의 경우처럼 작은 따옴표 문자가 사용되는 경우, regex 와 replacement 는 single quoted 문자열로 처리된다.


2.2.9. split 연산자

split /regex/, string 와 같이 사용하여 문자열을 쪼갤 수 있다. 이 경우 쪼개진 문자열의 리스트가 반환된다. regex는 어떤 문자열을 기준으로 쪼갤 것인지를 결정한다. 예를 들어 문자열을 단어단위로 쪼개려면,

    $x = "Calvin and Hobbes";
    @word = split /\s+/, $x;  # $word[0] = 'Calvin'
                              # $word[1] = 'and'
                              # $word[2] = 'Hobbes'

쉼표를 구분자로 사용한 문자열의 경우는,

    $x = "1.618,2.718,   3.142";
    @const = split /,\s*/, $x;  # $const[0] = '1.618'
                                # $const[1] = '2.718'
                                # $const[2] = '3.142'

만약 정규표현식을 공백으로 두면, 즉 // 과 같이 사용하면, 문자열은 각각의 문자로 쪼개지게 된다. 만약 정규표현식이 그룹을 가지고 있다면 그 그룹에 의해 매치된 부분도 함께 반환된다.

    $x = "/usr/bin";
    @parts = split m!(/)!, $x;  # $parts[0] = ''
                                # $parts[1] = '/'
                                # $parts[2] = 'usr'
                                # $parts[3] = '/'
                                # $parts[4] = 'bin'

이 경우는 정규표현식에 의해 첫번째 문자가 매치되었고, 첫번째 / 의 앞에 있는 문자열이 ''이므로 빈 문자열도 함께 반환된다.


2.2.10. 버그

없음.


2.3. SEE ALSO

이 페이지는 단지 "빠르게 시작하기"용 문서이다. 정규표현식에 대한 더 깊이있는 내용은 perlretut를 보고, reference page는 perlre를 봐라.


2.4. AUTHOR AND COPYRIGHT

Copyright (c) 2000 Mark Kvale All rights reserved.

This document may be distributed under the same terms as Perl itself.


2.4.1. Acknowledgments

The author would like to thank Mark-Jason Dominus, Tom Christiansen, Ilya Zakharevich, Brad Hughes, and Mike Giroux for all their helpful comments.

ID
Password
Join
Troglodytism does not necessarily imply a low cultural level.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2007-07-22 12:48:31
Processing time 0.0365 sec