ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Python/정규식 HOWTO
    코딩/Python 2024. 3. 4. 10:24
    728x90

    아래 내용은 Python reference를 번역한 것이다. 원본 내용은 제목의 링크를 참조한다.

    Regular Expression HOWTO

    Author:

    A.M. Kuchling <amk@amk.ca>

    Abstract

    This document is an introductory tutorial to using regular expressions in Python with the re module. It provides a gentler introduction than the corresponding section in the Library Reference.

    이 문서는 re 모듈과 함께 Python에서 정규식을 사용하는 방법에 대한 입문 튜토리얼이다. Library Reference의 해당 섹션보다 덜 딱딱한 소개를 제공한다.

    Introduction

    Regular expressions (called REs, or regexes, or regex patterns) are essentially a tiny, highly specialized programming language embedded inside Python and made available through the re module. Using this little language, you specify the rules for the set of possible strings that you want to match; this set might contain English sentences, or e-mail addresses, or TeX commands, or anything you like. You can then ask questions such as “Does this string match the pattern?”, or “Is there a match for the pattern anywhere in this string?”. You can also use REs to modify a string or to split it apart in various ways.

    Regular expression patterns are compiled into a series of bytecodes which are then executed by a matching engine written in C. For advanced use, it may be necessary to pay careful attention to how the engine will execute a given RE, and write the RE in a certain way in order to produce bytecode that runs faster. Optimization isn’t covered in this document, because it requires that you have a good understanding of the matching engine’s internals.

    The regular expression language is relatively small and restricted, so not all possible string processing tasks can be done using regular expressions. There are also tasks that can be done with regular expressions, but the expressions turn out to be very complicated. In these cases, you may be better off writing Python code to do the processing; while Python code will be slower than an elaborate regular expression, it will also probably be more understandable.

     

    정규식(RE, regexes 또는 regex 패턴이라고 함)은 본질적으로 Python에 내장된 작고 고도로 전문화된 프로그래밍 언어이며 re 모듈을 통해 사용할 수 있다. 이 작은 언어를 사용하여 일치시키려는 가능한 문자열 집합에 대한 규칙을 지정한다. 이 세트에는 영어 문장, 이메일 주소, TeX 명령 또는 원하는 모든 것이 포함될 수 있다. 그런 다음 "이 문자열이 패턴과 일치하는가?" 또는 "이 문자열의 어느 위치에나 패턴과 일치하는가?"와 같은 질문을 할 수 있다. RE를 사용하여 문자열을 수정하거나 다양한 방법으로 분할할 수도 있다.

    정규식 패턴은 일련의 바이트코드로 컴파일된 다음 C로 작성된 매칭 엔진에 의해 실행된다. 고급 사용의 경우 엔진이 주어진 RE를 어떻게 실행하는지 주의 깊게 살펴보고 더 빠르게 실행되는 바이트코드를 생성하기 위해 특정 방식으로 RE를 작성해야 할 수도 있다. 최적화를 위해서는 매칭 엔진의 내부 구조를 잘 이해해야 하기 때문에 이 문서에서는 최적화를 다루지 않는다.

    정규식 언어는 상대적으로 작고 제한되어 있으므로 정규식을 사용하여 가능한 모든 문자열 처리 작업을 수행할 수는 없다. 정규식으로 수행할 수 있는 작업도 있지만 표현식이 매우 복잡해진다. 이러한 경우 처리를 수행하기 위해 Python 코드를 작성하는 것이 더 나을 수 있다. Python 코드는 정교한 정규 표현식보다 속도가 느리지만 아마도 더 이해하기 쉬울 것이다.

    Simple Patterns

    We’ll start by learning about the simplest possible regular expressions. Since regular expressions are used to operate on strings, we’ll begin with the most common task: matching characters.

    For a detailed explanation of the computer science underlying regular expressions (deterministic and non-deterministic finite automata), you can refer to almost any textbook on writing compilers.

     

    가장 간단한 정규 표현식에 대해 배우는 것부터 시작한다. 정규식은 문자열에 대해 작동하는 데 사용되므로 가장 일반적인 작업인 문자 일치부터 시작한다.

    정규식(결정론적 및 비결정론적 유한 오토마타)의 기반이 되는 컴퓨터 과학에 대한 자세한 설명은 컴파일러 작성에 관한 거의 모든 교과서를 참조할 수 있다.

    Matching Characters

    Most letters and characters will simply match themselves. For example, the regular expression test will match the string test exactly. (You can enable a case-insensitive mode that would let this RE match Test or TEST as well; more about this later.)

    There are exceptions to this rule; some characters are special metacharacters, and don’t match themselves. Instead, they signal that some out-of-the-ordinary thing should be matched, or they affect other portions of the RE by repeating them or changing their meaning. Much of this document is devoted to discussing various metacharacters and what they do.

    Here’s a complete list of the metacharacters; their meanings will be discussed in the rest of this HOWTO.

     

    대부분의 문자와 문자는 단순히 자체적으로 일치한다. 예를 들어 정규식 테스트는 문자열 테스트와 정확하게 일치한다. (이 RE가 Test 또는 TEST와 일치하도록 대소문자를 구분하지 않는 모드를 활성화할 수 있다. 이에 대해서는 나중에 자세히 설명한다.)

    이 규칙에는 예외가 있다. 일부 문자는 특수 메타문자이므로 자체적으로 일치하지 않는다. 대신, 그들은 비정상적인 것이 일치해야 한다는 신호를 보내거나, 이를 반복하거나 의미를 변경하여 RE의 다른 부분에 영향을 미친다. 이 문서의 대부분은 다양한 메타 문자와 그 기능을 논의하는 데 할애된다.

    다음은 메타문자의 전체 목록이다. 그 의미는 이 HOWTO의 나머지 부분에서 논의될 것이다.

    . ^ $ * + ? { } [ ] \ | ( )

     

    The first metacharacters we’ll look at are [ and ]. They’re used for specifying a character class, which is a set of characters that you wish to match. Characters can be listed individually, or a range of characters can be indicated by giving two characters and separating them by a '-'. For example, [abc] will match any of the characters a, b, or c; this is the same as [a-c], which uses a range to express the same set of characters. If you wanted to match only lowercase letters, your RE would be [a-z].

    Metacharacters (except \) are not active inside classes. For example, [akm$] will match any of the characters 'a', 'k', 'm', or '$'; '$' is usually a metacharacter, but inside a character class it’s stripped of its special nature.

    You can match the characters not listed within the class by complementing the set. This is indicated by including a '^' as the first character of the class. For example, [^5] will match any character except '5'. If the caret appears elsewhere in a character class, it does not have special meaning. For example: [5^] will match either a '5' or a '^'.

    Perhaps the most important metacharacter is the backslash, \. As in Python string literals, the backslash can be followed by various characters to signal various special sequences. It’s also used to escape all the metacharacters so you can still match them in patterns; for example, if you need to match a [ or \, you can precede them with a backslash to remove their special meaning: \[ or \\.

    Some of the special sequences beginning with '\' represent predefined sets of characters that are often useful, such as the set of digits, the set of letters, or the set of anything that isn’t whitespace.

    Let’s take an example: \w matches any alphanumeric character. If the regex pattern is expressed in bytes, this is equivalent to the class [a-zA-Z0-9_]. If the regex pattern is a string, \w will match all the characters marked as letters in the Unicode database provided by the unicodedata module. You can use the more restricted definition of \w in a string pattern by supplying the re.ASCII flag when compiling the regular expression.

    The following list of special sequences isn’t complete. For a complete list of sequences and expanded class definitions for Unicode string patterns, see the last part of Regular Expression Syntax in the Standard Library reference. In general, the Unicode versions match any character that’s in the appropriate category in the Unicode database.

     

    우리가 살펴볼 첫 번째 메타 문자는 []이다. 일치시키려는 문자 집합인 문자 클래스를 지정하는 데 사용된다. 문자를 개별적으로 나열할 수도 있고, 두 문자를 제공하고 '-'로 구분하여 문자 범위를 표시할 수도 있다. 예를 들어, [abc]는 a, b 또는 c 문자와 일치한다. 이는 범위를 사용하여 동일한 문자 집합을 표현하는 [a-c]와 동일하다. 소문자만 일치시키려는 경우 RE는 [a-z]이다.

    메타 문자(\ 제외)는 클래스 내에서 활성화되지 않는다. 예를 들어, [akm$]은 'a', 'k', 'm' 또는 '$' 문자와 일치한다. '$'는 일반적으로 메타 문자이지만 문자 클래스 내에서는 특별한 특성이 제거된다.

    세트를 보완하여 클래스 내에 나열되지 않은 문자를 일치시킬 수 있다. 이는 클래스의 첫 번째 문자로 '^'를 포함하여 표시된다. 예를 들어, [^5]는 '5'를 제외한 모든 문자와 일치한다. 캐럿이 문자 클래스의 다른 곳에 나타나면 특별한 의미가 없다. 예를 들어, [5^]는 '5' 또는 '^'와 일치한다.

    아마도 가장 중요한 메타 문자는 백슬래시인 \일 것이다. Python 문자열 리터럴에서와 마찬가지로 백슬래시 뒤에는 다양한 특수 시퀀스를 나타내는 다양한 문자가 올 수 있다. 또한 모든 메타 문자를 이스케이프하여 패턴에서 일치시킬 수 있도록 하는 데에도 사용된다. 예를 들어, [ 또는 \를 일치시켜야 하는 경우 백슬래시를 앞에 붙여서 특별한 의미(\[ 또는 \\)를 제거할 수 있다.

    '\'로 시작하는 특수 시퀀스 중 일부는 숫자 세트, 문자 세트 또는 공백이 아닌 모든 항목 세트와 같이 종종 유용한 미리 정의된 문자 세트를 나타낸다.

    예를 들면 \w는 모든 영숫자 문자와 일치한다. 정규식 패턴이 바이트 단위로 표현되는 경우 이는 [a-zA-Z0-9_] 클래스와 동일하다. 정규식 패턴이 문자열인 경우 \w는 unicodedata 모듈에서 제공하는 유니코드 데이터베이스에서 문자로 표시된 모든 문자와 일치한다. 정규식을 컴파일할 때 re.ASCII 플래그를 제공하여 문자열 패턴에서 \w의 보다 제한된 정의를 사용할 수 있다.

    다음 특수 시퀀스 목록은 완전하지 않다. 유니코드 문자열 패턴에 대한 전체 시퀀스 목록과 확장된 클래스 정의를 보려면 표준 라이브러리 참조에서 정규식 구문의 마지막 부분을 참조한다. 일반적으로 유니코드 버전은 유니코드 데이터베이스의 해당 범주에 있는 모든 문자와 일치한다.


    \d

    Matches any decimal digit; this is equivalent to the class [0-9].

    모든 십진수와 일치한다. 이는 클래스 [0-9]와 동일하다.

     

    \D

    Matches any non-digit character; this is equivalent to the class [^0-9].

    숫자가 아닌 문자와 일치한다. 이는 클래스 [^0-9]와 동일하다.

     

    \s

    Matches any whitespace character; this is equivalent to the class [ \t\n\r\f\v].

    모든 공백 문자와 일치한다. 이는 클래스 [ \t\n\r\f\v]와 동일하다.

     

    \S

    Matches any non-whitespace character; this is equivalent to the class [^ \t\n\r\f\v].

    공백이 아닌 문자와 일치한다. 이는 클래스 [^ \t\n\r\f\v]와 동일하다.

     

    \w

    Matches any alphanumeric character; this is equivalent to the class [a-zA-Z0-9_].

    모든 영숫자 문자와 일치한다. 이는 [a-zA-Z0-9_] 클래스와 동일하다.

     

    \W

    Matches any non-alphanumeric character; this is equivalent to the class [^a-zA-Z0-9_].

    영숫자가 아닌 문자와 일치한다. 이는 [^a-zA-Z0-9_] 클래스와 동일하다.


    These sequences can be included inside a character class. For example, [\s,.] is a character class that will match any whitespace character, or ',' or '.'.

    The final metacharacter in this section is .. It matches anything except a newline character, and there’s an alternate mode (re.DOTALL) where it will match even a newline. . is often used where you want to match “any character”.

     

    이러한 시퀀스는 문자 클래스 내에 포함될 수 있다. 예를 들어, [\s,.]는 공백 문자나 ',' 또는 '.'와 일치하는 문자 클래스이다.

    이 섹션의 마지막 메타 문자는 .. 개행 문자를 제외한 모든 것과 일치하며 개행 문자와도 일치하는 대체 모드(re.DOTALL)가 있다. .은 "모든 문자"를 일치시키려는 경우에 자주 사용된다.

    Repeating Things

    Being able to match varying sets of characters is the first thing regular expressions can do that isn’t already possible with the methods available on strings. However, if that was the only additional capability of regexes, they wouldn’t be much of an advance. Another capability is that you can specify that portions of the RE must be repeated a certain number of times.

    The first metacharacter for repeating things that we’ll look at is *. * doesn’t match the literal character '*'; instead, it specifies that the previous character can be matched zero or more times, instead of exactly once.

    For example, ca*t will match 'ct' (0 'a' characters), 'cat' (1 'a'), 'caaat' (3 'a' characters), and so forth.

    Repetitions such as * are greedy; when repeating a RE, the matching engine will try to repeat it as many times as possible. If later portions of the pattern don’t match, the matching engine will then back up and try again with fewer repetitions.

    A step-by-step example will make this more obvious. Let’s consider the expression a[bcd]*b. This matches the letter 'a', zero or more letters from the class [bcd], and finally ends with a 'b'. Now imagine matching this RE against the string 'abcbd'.

    Step Matched Explanation
    2 abcbd The engine matches [bcd]*, going as far as it can, which is to the end of the string.
    3 Failure The engine tries to match b, but the current position is at the end of the string, so it fails.
    4 abcb Back up, so that [bcd]* matches one less character.
    5 Failure Try b again, but the current position is at the last character, which is a 'd'.
    6 abc Back up again, so that [bcd]* is only matching bc.
    6 abcb Try b again. This time the character at the current position is 'b', so it succeeds.

     

    다양한 문자 집합을 일치시킬 수 있는 것은 문자열에서 사용할 수 있는 메서드로는 아직 불가능한 것을 정규식이 수행할 수 있는 첫 번째 작업이다. 그러나 그것이 정규식의 유일한 추가 기능이라면 그다지 발전하지 않았을 것이다. 또 다른 기능은 RE의 일부가 특정 횟수만큼 반복되어야 함을 지정할 수 있다는 것이다.

    우리가 살펴볼 반복 항목에 대한 첫 번째 메타 문자는 *이다. *는 리터럴 문자 '*'와 일치하지 않는다. 대신, 이전 문자가 정확히 한 번이 아닌 0번 이상 일치할 수 있음을 지정한다.

    예를 들어, ca*t는 'ct'(0 'a' 문자), 'cat'(1 'a'), 'caaat'(3 'a' 문자) 등과 일치한다.

    *와 같은 반복은 탐욕적이다. RE를 반복할 때 매칭 엔진은 이를 가능한 한 많이 반복하려고 시도한다. 패턴의 이후 부분이 일치하지 않으면 일치 엔진이 백업되어 반복 횟수를 줄여 다시 시도한다.

    단계별 예제를 통해 이를 더욱 명확하게 알 수 있다. a[bcd]*b라는 표현을 생각해 본다. 이는 문자 'a', 클래스 [bcd]의 0개 이상의 문자와 일치하고 마지막으로 'b'로 끝난다. 이제 이 RE를 문자열 'abcbd'와 일치시키는 것을 상상해 보라.

    단계 일치 설명
    2 abcbd 엔진은 [bcd]*와 일치하여 문자열의 끝까지 가능한 한 멀리 이동한다.
    3 Failure 엔진은 b를 일치시키려고 시도하지만 현재 위치가 문자열의 끝이므로 실패한다.
    4 abcb [bcd]*와 일치하는 문자가 하나 줄어들도록 백업한다.
    5 Failure b를 다시 시도하지만 현재 위치는 마지막 문자인 'd'에 있다.
    6 abc 다시 백업하여 [bcd]*가 bc에만 일치하도록 한다.
    6 abcb b를 다시 시도. 이번에는 현재 위치의 문자가 'b'이므로 성공한다.

     

    The end of the RE has now been reached, and it has matched 'abcb'. This demonstrates how the matching engine goes as far as it can at first, and if no match is found it will then progressively back up and retry the rest of the RE again and again. It will back up until it has tried zero matches for [bcd]*, and if that subsequently fails, the engine will conclude that the string doesn’t match the RE at all.

    Another repeating metacharacter is +, which matches one or more times. Pay careful attention to the difference between * and +; * matches zero or more times, so whatever’s being repeated may not be present at all, while + requires at least one occurrence. To use a similar example, ca+t will match 'cat' (1 'a'), 'caaat' (3 'a's), but won’t match 'ct'.

    There are two more repeating operators or quantifiers. The question mark character, ?, matches either once or zero times; you can think of it as marking something as being optional. For example, home-?brew matches either 'homebrew' or 'home-brew'.

    The most complicated quantifier is {m,n}, where m and n are decimal integers. This quantifier means there must be at least m repetitions, and at most n. For example, a/{1,3}b will match 'a/b', 'a//b', and 'a///b'. It won’t match 'ab', which has no slashes, or 'a////b', which has four.

    You can omit either m or n; in that case, a reasonable value is assumed for the missing value. Omitting m is interpreted as a lower limit of 0, while omitting n results in an upper bound of infinity.

    The simplest case {m} matches the preceding item exactly m times. For example, a/{2}b will only match 'a//b'.

    Readers of a reductionist bent may notice that the three other quantifiers can all be expressed using this notation. {0,} is the same as *, {1,} is equivalent to +, and {0,1} is the same as ?. It’s better to use *, +, or ? when you can, simply because they’re shorter and easier to read.

     

    이제 RE의 끝에 도달했으며 'abcb'와 일치했다. 이는 일치 엔진이 처음에 최대한 멀리 가는 방법을 보여 주며, 일치 항목이 발견되지 않으면 점진적으로 백업하고 RE의 나머지 부분을 계속해서 다시 시도한다. [bcd]*에 대해 0개의 일치 항목을 시도할 때까지 백업하고 이후에 실패하면 엔진은 문자열이 RE와 전혀 일치하지 않는다고 결론을 내린다.

    또 다른 반복 메타 문자는 +이며, 이는 한 번 이상 일치한다. *와 +의 차이에 주의한다. *는 0회 이상 일치하므로 반복되는 항목은 전혀 존재하지 않을 수 있지만 +는 최소한 한 번 이상 일치해야 한다. 비슷한 예를 사용하려면 ca+t는 'cat'(1 'a'), 'caaat'(3 'a')와 일치하지만 'ct'와는 일치하지 않는다.

    반복 연산자나 수량자가 두 개 더 있다. 물음표 문자 ?는 한 번 또는 0번 일치한다. 무언가를 선택사항으로 표시하는 것으로 생각할 수 있다. 예를 들어 home-?brew는 'homebrew' 또는 'home-brew'와 일치한다.

    가장 복잡한 수량자는 {m,n}이며, 여기서 m과 n은 십진 정수이다. 이 수량자는 최소 m회 반복, 최대 n회 반복이 있어야 함을 의미한다. 예를 들어, a/{1,3}b는 'a/b', 'a//b' 및 'a///b'와 일치한다. 슬래시가 없는 'ab' 또는 슬래시가 4개인 'a////b'와 일치하지 않는다.

    m 또는 n을 생략할 수 있다. 이 경우 결측값에 대해 합리적인 값이 가정된다. m을 생략하면 하한이 0으로 해석되고, n을 생략하면 상한이 무한대가 된다.

    가장 간단한 경우인 {m}은 이전 항목과 정확히 m번 일치한다. 예를 들어, a/{2}b는 'a//b'에만 일치한다.

    환원주의적 경향을 지닌 독자들은 세 가지 다른 수량자가 모두 이 표기법을 사용하여 표현될 수 있다는 것을 알 수 있다. {0,}는 *와 동일하고, {1,}은 +와 동일하며, {0,1}은 ?와 동일하다. *, + 또는 ?를 사용하는 것이 더 좋다. 가능하다면 더 짧고 읽기 쉽기 때문이다.

    Using Regular Expressions

    Now that we’ve looked at some simple regular expressions, how do we actually use them in Python? The re module provides an interface to the regular expression engine, allowing you to compile REs into objects and then perform matches with them.

     

    이제 몇 가지 간단한 정규식을 살펴보았으니 Python에서 이를 실제로 어떻게 사용할까? re 모듈은 정규식 엔진에 대한 인터페이스를 제공하여 RE를 객체로 컴파일한 다음 해당 객체와 일치를 수행할 수 있도록 한다.

    Compiling Regular Expressions

    Regular expressions are compiled into pattern objects, which have methods for various operations such as searching for pattern matches or performing string substitutions.

     

    정규식은 패턴 일치 검색이나 문자열 대체 수행과 같은 다양한 작업을 위한 메서드가 있는 패턴 개체로 컴파일된다.

    import re
    p = re.compile('ab*')
    p
    re.compile('ab*')

     

    re.compile() also accepts an optional flags argument, used to enable various special features and syntax variations. We’ll go over the available settings later, but for now a single example will do:

     

    re.compile()은 다양한 특수 기능과 구문 변형을 활성화하는 데 사용되는 선택적 플래그 인수도 허용한다. 사용 가능한 설정에 대해서는 나중에 살펴본다. 하지만 지금은 단일 예만 사용한다.

    p = re.compile('ab*', re.IGNORECASE)

     

    The RE is passed to re.compile() as a string. REs are handled as strings because regular expressions aren’t part of the core Python language, and no special syntax was created for expressing them. (There are applications that don’t need REs at all, so there’s no need to bloat the language specification by including them.) Instead, the re module is simply a C extension module included with Python, just like the socket or zlib modules.

    Putting REs in strings keeps the Python language simpler, but has one disadvantage which is the topic of the next section.

     

    RE는 re.compile()에 문자열로 전달된다. RE는 정규식이 핵심 Python 언어의 일부가 아니고 이를 표현하기 위해 생성된 특별한 구문이 없기 때문에 문자열로 처리된다. (RE가 전혀 필요하지 않은 응용 프로그램이 있으므로 이를 포함하여 언어 사양을 부풀릴 필요가 없다.) 대신 re 모듈은 소켓 또는 zlib 모듈과 마찬가지로 단순히 Python에 포함된 C 확장 모듈이다.

    RE를 문자열에 넣으면 Python 언어가 더 단순해 지지만 다음 섹션의 주제인 한 가지 단점이 있다.

    The Backslash Plague

    As stated earlier, regular expressions use the backslash character ('\') to indicate special forms or to allow special characters to be used without invoking their special meaning. This conflicts with Python’s usage of the same character for the same purpose in string literals.

    Let’s say you want to write a RE that matches the string \section, which might be found in a LaTeX file. To figure out what to write in the program code, start with the desired string to be matched. Next, you must escape any backslashes and other metacharacters by preceding them with a backslash, resulting in the string \\section. The resulting string that must be passed to re.compile() must be \\section. However, to express this as a Python string literal, both backslashes must be escaped again.

    Characters Stage
    \\section Escaped backslash for re.compile()
    "\\\\section" Escaped backslashes for a string literal

     

    앞에서 설명한 대로 정규식은 백슬래시 문자('\')를 사용하여 특수 형식을 나타내거나 특수 문자가 특별한 의미를 호출하지 않고 사용될 수 있도록 한다. 이는 문자열 리터럴에서 동일한 목적으로 Python이 동일한 문자를 사용하는 것과 충돌한다.

    LaTeX 파일에서 찾을 수 있는 \section 문자열과 일치하는 RE를 작성한다고 가정해 본다. 프로그램 코드에 무엇을 쓸지 알아보려면 일치시키려는 문자열부터 시작한다. 다음으로, 백슬래시와 기타 메타 문자 앞에 백슬래시를 붙여 이스케이프해야 한다. 그러면 \\section이라는 문자열이 생성된다. re.compile()에 전달되어야 하는 결과 문자열은 \\section이어야 한다. 그러나 이를 Python 문자열 리터럴로 표현하려면 두 백슬래시를 다시 이스케이프해야 한다.

    캐릭터 단계
    \\section re.compile()에 대해 이스케이프된 백슬래시
    "\\\\section" 문자열 리터럴의 이스케이프된 백슬래시

     

    In short, to match a literal backslash, one has to write '\\\\' as the RE string, because the regular expression must be \\, and each backslash must be expressed as \\ inside a regular Python string literal. In REs that feature backslashes repeatedly, this leads to lots of repeated backslashes and makes the resulting strings difficult to understand.

    The solution is to use Python’s raw string notation for regular expressions; backslashes are not handled in any special way in a string literal prefixed with 'r', so r"\n" is a two-character string containing '\' and 'n', while "\n" is a one-character string containing a newline. Regular expressions will often be written in Python code using this raw string notation.

    In addition, special escape sequences that are valid in regular expressions, but not valid as Python string literals, now result in a DeprecationWarning and will eventually become a SyntaxError, which means the sequences will be invalid if raw string notation or escaping the backslashes isn’t used.

     

    간단히 말해서, 리터럴 백슬래시와 일치시키려면 RE 문자열로 '\\\\'를 써야 한다. 왜냐하면 정규 표현식은 \\여야 하고 각 백슬래시는 일반 Python 문자열 리터럴 내에서 \\로 표현되어야 하기 때문이다. 백슬래시를 반복적으로 사용하는 RE에서는 이로 인해 백슬래시가 많이 반복되어 결과 문자열을 이해하기 어렵게 만든다.

    해결책은 정규식에 Python의 원시 문자열 표기법을 사용하는 것이다. 백슬래시는 'r' 접두사가 붙은 문자열 리터럴에서 특별한 방식으로 처리되지 않는다. 따라서 r"\n"은 '\'와 'n'을 포함하는 2문자 문자열이고, "\n"은 1문자 문자열이다. 개행 문자를 포함한다. 정규식은 종종 이 원시 문자열 표기법을 사용하여 Python 코드로 작성된다.

    또한 정규식에서는 유효하지만 Python 문자열 리터럴로는 유효하지 않은 특수 이스케이프 시퀀스는 이제 DeprecationWarning을 발생시키고 결국 SyntaxError가 된다. 이는 원시 문자열 표기 또는 백슬래시 이스케이프가 사용되지 않으면 시퀀스는 유효하지 않게 된다는 의미이다.

    Regular String Raw string
    "\\\\section" r"\\section"
    "\\w+\\s+\\1" r"\w+\s+\1"

    Performing Matches

    Once you have an object representing a compiled regular expression, what do you do with it? Pattern objects have several methods and attributes. Only the most significant ones will be covered here; consult the re docs for a complete listing.

    Method/Attribute Purpose
    search() Scan through a string, looking for any location where this RE matches.
    findall() Find all substrings where the RE matches, and returns them as a list.
    finditer() Find all substrings where the RE matches, and returns them as an iterator.

     

    컴파일된 정규 표현식을 나타내는 객체가 있으면 이를 어떻게 할까? 패턴 객체에는 여러 가지 메서드와 속성이 있다. 여기서는 가장 중요한 것만 다룬다. 전체 목록을 보려면 re 문서를 참조한다.

    Method/Attribute Purpose
    search() 문자열을 스캔하여 이 RE가 일치하는 위치를 찾는다.
    findall() RE가 일치하는 모든 하위 문자열을 찾아 list로 반환한다.
    finditer() RE가 일치하는 모든 하위 문자열을 찾아 반복자로 반환한다.

     

    match() and search() return None if no match can be found. If they’re successful, a match object instance is returned, containing information about the match: where it starts and ends, the substring it matched, and more.

    You can learn about this by interactively experimenting with the re module.

    This HOWTO uses the standard Python interpreter for its examples. First, run the Python interpreter, import the re module, and compile a RE:

     

    match() 및 search()는 일치하는 항목을 찾을 수 없으면 None을 반환한다. 성공하면 일치에 대한 정보(시작 및 종료 위치, 일치하는 하위 문자열 등)가 포함된 일치 개체 인스턴스가 반환된다.

    re 모듈을 대화형으로 실험하여 이에 대해 배울 수 있다.

    이 HOWTO에서는 예제로 표준 Python 인터프리터를 사용한다. 먼저 Python 인터프리터를 실행하고 re 모듈을 가져온 다음 RE를 컴파일한다.

    import re
    p = re.compile('[a-z]+')
    p
    re.compile('[a-z]+')

     

    Now, you can try matching various strings against the RE [a-z]+. An empty string shouldn’t match at all, since + means ‘one or more repetitions’. match() should return None in this case, which will cause the interpreter to print no output. You can explicitly print the result of match() to make this clear.

     

    이제 RE [a-z]+에 대해 다양한 문자열을 일치시켜 볼 수 있다. +는 '한 번 이상 반복'을 의미하므로 빈 문자열은 전혀 일치하지 않아야 한다. match()는 이 경우 None을 반환해야 하며, 이로 인해 인터프리터는 출력을 인쇄하지 않게 된다. 이를 명확하게 하기 위해 match()의 결과를 명시적으로 인쇄할 수 있다.

    p.match("")
    print(p.match(""))
    None

     

    Now, let’s try it on a string that it should match, such as tempo. In this case, match() will return a match object, so you should store the result in a variable for later use.

     

    이제 tempo 등 일치해야 하는 문자열에 시도해 본다. 이 경우 match()는 일치 개체를 반환하므로 나중에 사용할 수 있도록 결과를 변수에 저장해야 한다.

    m = p.match('tempo')
    m
    <re.Match object; span=(0, 5), match='tempo'>

     

    Now you can query the match object for information about the matching string. Match object instances also have several methods and attributes; the most important ones are:

    Method/Attribute Purpose
    start() Return the starting position of the match
    end() Return the ending position of the match
    span() Return a tuple containing the (start, end) positions of the match

     

    이제 일치하는 문자열에 대한 정보를 일치 개체에 쿼리할 수 있다. 일치 개체 인스턴스에는 여러 메서드와 속성도 있다. 가장 중요한 것들은 다음과 같다:

    Method/Attribute Purpose
    start() 일치의 시작 위치를 반환한다.
    end() 일치의 종료 위치를 반환한다.
    span() 일치 항목의 (시작, 끝) 위치를 포함하는 튜플을 반환한다.

     

    Trying these methods will soon clarify their meaning:

     

    이러한 방법을 시도해 보면 곧 그 의미가 명확해질 것이다.

    m.group()
    'tempo'
    m.start(), m.end()
    (0, 5)
    m.span()
    (0, 5)

     

    group() returns the substring that was matched by the RE. start() and end() return the starting and ending index of the match. span() returns both start and end indexes in a single tuple. Since the match() method only checks if the RE matches at the start of a string, start() will always be zero. However, the search() method of patterns scans through the string, so the match may not start at zero in that case.

     

    group()은 RE와 일치하는 하위 문자열을 반환한다. start() 및 end()는 일치 항목의 시작 및 끝 인덱스를 반환한다. span()은 단일 튜플에서 시작 및 끝 인덱스를 모두 반환한다. match() 메소드는 RE가 문자열 시작 부분에서 일치하는지 확인하기 때문에 start()는 항상 0이 된다. 그러나 패턴의 search() 메서드는 문자열을 검색하므로 이 경우 일치 항목이 0에서 시작되지 않을 수 있다.

    print(p.match('::: message'))
    None
    m = p.search('::: message'); print(m)
    <re.Match object; span=(4, 11), match='message'>
    m.group()
    'message'
    m.span()
    (4, 11)

     

    In actual programs, the most common style is to store the match object in a variable, and then check if it was None. This usually looks like:

     

    실제 프로그램에서 가장 일반적인 스타일은 일치 개체를 변수에 저장한 다음 None인지 확인하는 것이다. 이는 일반적으로 다음과 같다.

    p = re.compile( ... )
    m = p.match( 'string goes here' )
    if m:
        print('Match found: ', m.group())
    else:
        print('No match')

     

    Two pattern methods return all of the matches for a pattern. findall() returns a list of matching strings:

     

    두 가지 패턴 메서드는 패턴과 일치하는 모든 항목을 반환한다. findall()은 일치하는 문자열 목록을 반환한다.

    p = re.compile(r'\d+')
    p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
    ['12', '11', '10']

     

    The r prefix, making the literal a raw string literal, is needed in this example because escape sequences in a normal “cooked” string literal that are not recognized by Python, as opposed to regular expressions, now result in a DeprecationWarning and will eventually become a SyntaxError. See The Backslash Plague.

    findall() has to create the entire list before it can be returned as the result. The finditer() method returns a sequence of match object instances as an iterator:

     

    정규 표현식과 달리 Python에서 인식되지 않는 일반적인 "조리된" 문자열 리터럴의 이스케이프 시퀀스는 이 예제에서 이제 DeprecationWarning을 발생시키고 결국에는 구문 오류가 되기 때문에 리터럴을 원시 문자열 리터럴로 만드는 r 접두사가 필요하다.

    findall()은 결과로 반환되기 전에 전체 목록을 생성해야 한다. finditer() 메소드는 일련의 일치 객체 인스턴스를 반복자로 반환한다.

    iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
    iterator
    <callable_iterator object at 0x...>
    for match in iterator:
        print(match.span())
    
    (0, 2)
    (22, 24)
    (29, 31)

    Module-Level Functions

    You don’t have to create a pattern object and call its methods; the re module also provides top-level functions called match(), search(), findall(), sub(), and so forth. These functions take the same arguments as the corresponding pattern method with the RE string added as the first argument, and still return either None or a match object instance.

     

    패턴 개체를 만들고 해당 메서드를 호출할 필요가 없다. re 모듈은 match(), search(), findall(), sub() 등의 최상위 함수도 제공한다. 이러한 함수는 첫 번째 인수로 추가된 RE 문자열을 사용하여 해당 패턴 메서드와 동일한 인수를 사용하며 여전히 None 또는 일치 개체 인스턴스를 반환한다.

    print(re.match(r'From\s+', 'Fromage amk'))
    None
    re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998')
    <re.Match object; span=(0, 5), match='From '>

     

    Under the hood, these functions simply create a pattern object for you and call the appropriate method on it. They also store the compiled object in a cache, so future calls using the same RE won’t need to parse the pattern again and again.

    Should you use these module-level functions, or should you get the pattern and call its methods yourself? If you’re accessing a regex within a loop, pre-compiling it will save a few function calls. Outside of loops, there’s not much difference thanks to the internal cache.

     

    내부적으로 이러한 함수는 단순히 패턴 개체를 생성하고 그에 대한 적절한 메서드를 호출한다. 또한 컴파일된 개체를 캐시에 저장하므로 동일한 RE를 사용하는 향후 호출에서는 패턴을 반복해서 구문 분석할 필요가 없다.

    이러한 모듈 수준 함수를 사용해야 할까, 아니면 패턴을 가져와 해당 메서드를 직접 호출해야 할까? 루프 내에서 정규식에 액세스하는 경우 미리 컴파일하면 몇 가지 함수 호출이 절약된다. 루프 외부에는 내부 캐시 덕분에 큰 차이가 없다.

    Compilation Flags

    Compilation flags let you modify some aspects of how regular expressions work. Flags are available in the re module under two names, a long name such as IGNORECASE and a short, one-letter form such as I. (If you’re familiar with Perl’s pattern modifiers, the one-letter forms use the same letters; the short form of re.VERBOSE is re.X, for example.) Multiple flags can be specified by bitwise OR-ing them; re.I | re.M sets both the I and M flags, for example.

    Here’s a table of the available flags, followed by a more detailed explanation of each one.

    Flag Meaning
    DOTALL, S Make . match any character, including newlines.
    IGNORECASE, I Do case-insensitive matches.
    LOCALE, L Do a locale-aware match.
    MULTILINE, M Multi-line matching, affecting ^ and $.
    VERBOSE, X (for ‘extended’) Enable verbose REs, which can be organized more cleanly and understandably

     

    컴파일 플래그를 사용하면 정규식이 작동하는 방식의 일부 사항을 수정할 수 있다. 플래그는 re 모듈에서 두 가지 이름, 즉 IGNORECASE와 같은 긴 이름과 I와 같은 짧은 한 글자 형식으로 사용할 수 있다. (Perl의 패턴 수정자에 익숙하다면 한 글자 형식은 동일한 문자를 사용한다. 예를 들어 re.VERBOSE의 짧은 형식은 re.X이다.) 여러 플래그는 비트 단위 OR을 사용하여 지정할 수 있다. 예를 들어 re.I | re.M 은 I 및 M 플래그를 모두 설정한다.

    다음은 사용 가능한 플래그 표와 각 플래그에 대한 자세한 설명이다.

    Flag Meaning
    DOTALL, S 개행 문자를 포함한 모든 문자와 일치하도록 .을 만든다.
    IGNORECASE, I 대소문자를 구분하지 않고 일치시킨다.
    LOCALE, L 로캘 인식 일치를 수행한다.
    MULTILINE, M ^$에 영향을 미치는 여러 줄 일치.
    VERBOSE, X (for ‘extended’) 보다 깔끔하고 이해하기 쉽게 정리할 수 있는 verbose RE를 활성화한다.

    re.I

    re.IGNORECASE

    Perform case-insensitive matching; character class and literal strings will match letters by ignoring case. For example, [A-Z] will match lowercase letters, too. Full Unicode matching also works unless the ASCII flag is used to disable non-ASCII matches. When the Unicode patterns [a-z] or [A-Z] are used in combination with the IGNORECASE flag, they will match the 52 ASCII letters and 4 additional non-ASCII letters: ‘İ’ (U+0130, Latin capital letter I with dot above), ‘ı’ (U+0131, Latin small letter dotless i), ‘ſ’ (U+017F, Latin small letter long s) and ‘K’ (U+212A, Kelvin sign). Spam will match 'Spam', 'spam', 'spAM', or 'ſpam' (the latter is matched only in Unicode mode). This lowercasing doesn’t take the current locale into account; it will if you also set the LOCALE flag.

     

    대소문자를 구분하지 않고 일치를 수행한다. 문자 클래스와 리터럴 문자열은 대소문자를 무시하여 문자와 일치한다. 예를 들어, [A-Z]는 소문자와도 일치한다. ASCII 플래그가 비ASCII 일치를 비활성화하는 데 사용되지 않는 한 전체 유니코드 일치도 작동한다. 유니코드 패턴 [a-z] 또는 [A-Z]가 IGNORECASE 플래그와 함께 사용되면 52개의 ASCII 문자와 4개의 추가 비ASCII 문자인 'İ'(U+0130, 위에 점이 있는 라틴 대문자 I), 'ı'(U+0131, 점이 없는 라틴 소문자 i), 'ſ'(U+017F, 긴 라틴 소문자 s) 및 'K'(U+212A, 켈빈 기호)와 일치한다. 스팸은 'Spam', 'spam', 'spAM' 또는 'ſpam'과 일치한다(후자는 유니코드 모드에서만 일치한다). 이 소문자화는 현재 로케일을 고려하지 않는다. LOCALE 플래그도 설정하면 그렇게 된다.

     

    re.L

    re.LOCALE

    Make \w, \W, \b, \B and case-insensitive matching dependent on the current locale instead of the Unicode database.

    Locales are a feature of the C library intended to help in writing programs that take account of language differences. For example, if you’re processing encoded French text, you’d want to be able to write \w+ to match words, but \w only matches the character class [A-Za-z] in bytes patterns; it won’t match bytes corresponding to é or ç. If your system is configured properly and a French locale is selected, certain C functions will tell the program that the byte corresponding to é should also be considered a letter. Setting the LOCALE flag when compiling a regular expression will cause the resulting compiled object to use these C functions for \w; this is slower, but also enables \w+ to match French words as you’d expect. The use of this flag is discouraged in Python 3 as the locale mechanism is very unreliable, it only handles one “culture” at a time, and it only works with 8-bit locales. Unicode matching is already enabled by default in Python 3 for Unicode (str) patterns, and it is able to handle different locales/languages.

     

    유니코드 데이터베이스 대신 현재 로케일에 따라 \w, \W, \b, \B 및 대소문자를 구분하지 않는 일치를 만든다.

    로케일은 언어 차이를 고려한 프로그램 작성을 돕기 위한 C 라이브러리의 기능이다. 예를 들어, 인코딩된 프랑스어 텍스트를 처리하는 경우 단어와 일치하도록 \w+를 쓸 수 있지만 \w는 바이트 패턴의 문자 클래스 [A-Za-z]에만 일치한다. é 또는 ç에 해당하는 바이트와 일치하지 않는다. 시스템이 올바르게 구성되고 프랑스어 로케일이 선택된 경우 특정 C 기능은 é에 해당하는 바이트도 문자로 간주되어야 함을 프로그램에 알려준다. 정규식을 컴파일할 때 LOCALE 플래그를 설정하면 컴파일된 결과 개체가 \w에 대해 이러한 C 함수를 사용하게 된다. 이는 속도가 느리지만 예상대로 \w+가 프랑스어 단어와 일치하도록 한다. 로케일 메커니즘은 매우 불안정하고 한 번에 하나의 "문화권"만 처리하며 8비트 로케일에서만 작동하므로 Python 3에서는 이 플래그의 사용을 권장하지 않는다. 유니코드 일치는 이미 Python 3에서 유니코드(str) 패턴에 대해 기본적으로 활성화되어 있으며 다양한 로케일/언어를 처리할 수 있다.

     

    re.M

    re.MULTILINE

    (^ and $ haven’t been explained yet; they’ll be introduced in section More Metacharacters.)

    Usually ^ matches only at the beginning of the string, and $ matches only at the end of the string and immediately before the newline (if any) at the end of the string. When this flag is specified, ^ matches at the beginning of the string and at the beginning of each line within the string, immediately following each newline. Similarly, the $ metacharacter matches either at the end of the string and at the end of each line (immediately preceding each newline).

     

    (^$는 아직 설명되지 않았다. 추가 메타문자 섹션에서 소개된다.)

    일반적으로 ^는 문자열의 시작 부분에서만 일치하고 $는 문자열 끝과 문자열 끝의 개행 문자(있는 경우) 바로 앞에서만 일치한다. 이 플래그가 지정되면 ^는 문자열의 시작 부분과 문자열 내 각 줄의 시작 부분, 각 개행 바로 다음에 일치한다. 마찬가지로 $ 메타 문자는 문자열 끝과 각 줄 끝(각 줄 바꿈 바로 앞)에서 일치한다.

     

    re.S

    re.DOTALL

    Makes the '.' special character match any character at all, including a newline; without this flag, '.' will match anything except a newline.

     

    줄 바꿈을 포함하여 모든 문자와 일치하는 '.' 특수 문자를 만든다. 이 플래그가 없으면 '.' 줄 바꿈을 제외한 모든 항목과 일치한다.

     

    re.A

    re.ASCII

    Make \w, \W, \b, \B, \s and \S perform ASCII-only matching instead of full Unicode matching. This is only meaningful for Unicode patterns, and is ignored for byte patterns.

     

    \w, \W, \b, \B, \s\S가 전체 유니코드 일치 대신 ASCII 전용 일치를 수행하도록 만든다. 이는 유니코드 패턴에만 의미가 있으며 바이트 패턴에서는 무시된다.

     

    re.X

    re.VERBOSE

    This flag allows you to write regular expressions that are more readable by granting you more flexibility in how you can format them. When this flag has been specified, whitespace within the RE string is ignored, except when the whitespace is in a character class or preceded by an unescaped backslash; this lets you organize and indent the RE more clearly. This flag also lets you put comments within a RE that will be ignored by the engine; comments are marked by a '#' that’s neither in a character class or preceded by an unescaped backslash.

    For example, here’s a RE that uses re.VERBOSE; see how much easier it is to read?

     

    이 플래그를 사용하면 형식 지정 방법에 더 많은 유연성을 부여하여 더 읽기 쉬운 정규식을 작성할 수 있다. 이 플래그가 지정되면 공백이 문자 클래스에 있거나 이스케이프되지 않은 백슬래시가 앞에 오는 경우를 제외하고 RE 문자열 내의 공백은 무시된다. 이렇게 하면 RE를 더 명확하게 구성하고 들여쓰기할 수 있다. 또한 이 플래그를 사용하면 엔진에서 무시되는 RE 내에 주석을 넣을 수 있다. 주석은 문자 클래스에 속하지 않거나 이스케이프되지 않은 백슬래시가 앞에 오는 '#'으로 표시된다.

    예를 들어, re.VERBOSE를 사용하는 RE가 있다. 읽기가 얼마나 쉬운지 보라?

    charref = re.compile(r"""
        &[#]                # Start of a numeric entity reference
        (
            0[0-7]+         # Octal form
            | [0-9]+          # Decimal form
            | x[0-9a-fA-F]+   # Hexadecimal form
        )
        ;                   # Trailing semicolon
    """, re.VERBOSE)

     

    Without the verbose setting, the RE would look like this:

     

    verbose 설정이 없으면 RE는 다음과 같다.

    charref = re.compile("&#(0[0-7]+"
        "|[0-9]+"
        "|x[0-9a-fA-F]+);")

     

    In the above example, Python’s automatic concatenation of string literals has been used to break up the RE into smaller pieces, but it’s still more difficult to understand than the version using re.VERBOSE.

     

    위의 예에서 Python의 문자열 리터럴 자동 연결은 RE를 더 작은 조각으로 나누는 데 사용되었지만 re.VERBOSE를 사용하는 버전보다 여전히 이해하기가 더 어렵다.

    More Pattern Power

    So far we’ve only covered a part of the features of regular expressions. In this section, we’ll cover some new metacharacters, and how to use groups to retrieve portions of the text that was matched.

     

    지금까지 우리는 정규식의 기능 중 일부만을 다루었다. 이 섹션에서는 몇 가지 새로운 메타 문자와 그룹을 사용하여 일치하는 텍스트 부분을 검색하는 방법을 다룬다.

    More Metacharacters

    There are some metacharacters that we haven’t covered yet. Most of them will be covered in this section.

    Some of the remaining metacharacters to be discussed are zero-width assertions. They don’t cause the engine to advance through the string; instead, they consume no characters at all, and simply succeed or fail. For example, \b is an assertion that the current position is located at a word boundary; the position isn’t changed by the \b at all. This means that zero-width assertions should never be repeated, because if they match once at a given location, they can obviously be matched an infinite number of times.

     

    아직 다루지 않은 메타문자가 있다. 이 섹션에서는 대부분을 다룰 것이다.

    논의할 나머지 메타 문자 중 일부는 너비가 0인 어서션이다. 이들은 엔진이 스트링을 통해 전진하도록 하지 않는다. 대신 문자를 전혀 소비하지 않고 단순히 성공하거나 실패한다. 예를 들어, \b는 현재 위치가 단어 경계에 있다는 어서션이다. 위치는 \b에 의해 전혀 변경되지 않는다. 즉, 너비가 0인 어서션은 절대 반복되어서는 안 된다. 주어진 위치에서 한 번 일치하면 분명히 무한히 일치할 수 있기 때문이다.

     

    Alternation, or the “or” operator. If A and B are regular expressions, A|B will match any string that matches either A or B. | has very low precedence in order to make it work reasonably when you’re alternating multi-character strings. Crow|Servo will match either 'Crow' or 'Servo', not 'Cro', a 'w' or an 'S', and 'ervo'.

    To match a literal '|', use \|, or enclose it inside a character class, as in [|].

     

    대체 또는 “or” 연산자이다. A와 B가 정규식인 경우 A|B는 A 또는 B와 일치하는 모든 문자열과 일치한다. 다중 문자 문자열을 교대로 사용할 때 합리적으로 작동하도록 하기 위해 |는 우선 순위가 매우 낮다. Crow|Servo는 'Cro', 'w' 또는 'S' 및 'ervo'가 아닌 'Crow' 또는 'Servo'와 일치한다.

    리터럴 '|'을 일치시키려면 \|를 사용하거나 [|]와 같이 문자 클래스 안에 넣는다.

     

    ^

    Matches at the beginning of lines. Unless the MULTILINE flag has been set, this will only match at the beginning of the string. In MULTILINE mode, this also matches immediately after each newline within the string.

    For example, if you wish to match the word From only at the beginning of a line, the RE to use is ^From.

     

    줄의 시작 부분에서 일치한다. MULTILINE 플래그가 설정되지 않은 한 이는 문자열의 시작 부분에서만 일치한다. MULTILINE 모드에서는 문자열 내의 각 개행 바로 뒤에도 일치한다.

    예를 들어 줄 시작 부분에서만 From이라는 단어를 일치시키려는 경우 사용할 RE는 ^From이다.

    print(re.search('^From', 'From Here to Eternity'))
    <re.Match object; span=(0, 4), match='From'>
    print(re.search('^From', 'Reciting From Memory'))
    None

     

    To match a literal '^', use \^.

     

    리터럴 '^'을 일치시키려면 \^를 사용한다.

     

    $

    Matches at the end of a line, which is defined as either the end of the string, or any location followed by a newline character.

     

    문자열의 끝 또는 개행 문자가 뒤에 오는 위치로 정의되는 줄의 끝에서 일치한다.

    print(re.search('}$', '{block}'))
    <re.Match object; span=(6, 7), match='}'>
    print(re.search('}$', '{block} '))
    None
    print(re.search('}$', '{block}\n'))
    <re.Match object; span=(6, 7), match='}'>

     

    To match a literal '$', use \$ or enclose it inside a character class, as in [$].

     

    리터럴 '$'를 일치시키려면 \$를 사용하거나 [$]와 같이 문자 클래스 안에 넣는다.

     

    \A

    Matches only at the start of the string. When not in MULTILINE mode, \A and ^ are effectively the same. In MULTILINE mode, they’re different: \A still matches only at the beginning of the string, but ^ may match at any location inside the string that follows a newline character.

     

    문자열의 시작 부분에서만 일치한다. MULTILINE 모드가 아닌 경우 \A와 ^는 사실상 동일하다. MULTILINE 모드에서는 다르다. \A는 여전히 문자열의 시작 부분에서만 일치하지만 ^는 개행 문자 다음에 오는 문자열 내의 모든 위치에서 일치할 수 있다.

     

    \Z

    Matches only at the end of the string.

     

    문자열 끝에서만 일치한다.

     

    \b

    Word boundary. This is a zero-width assertion that matches only at the beginning or end of a word. A word is defined as a sequence of alphanumeric characters, so the end of a word is indicated by whitespace or a non-alphanumeric character.

    The following example matches class only when it’s a complete word; it won’t match when it’s contained inside another word.

     

    단어 경계. 이는 단어의 시작이나 끝에서만 일치하는 너비가 없는 어서션이다. 단어는 일련의 영숫자 문자로 정의되므로 단어의 끝은 공백이나 영숫자가 아닌 문자로 표시된다.

    다음 예는 완전한 단어인 경우에만 class와 일치한다. 다른 단어 안에 포함되면 일치하지 않는다.

    p = re.compile(r'\bclass\b')
    print(p.search('no class at all'))
    <re.Match object; span=(3, 8), match='class'>
    print(p.search('the declassified algorithm'))
    None
    print(p.search('one subclass is'))
    None

     

    There are two subtleties you should remember when using this special sequence. First, this is the worst collision between Python’s string literals and regular expression sequences. In Python’s string literals, \b is the backspace character, ASCII value 8. If you’re not using raw strings, then Python will convert the \b to a backspace, and your RE won’t match as you expect it to. The following example looks the same as our previous RE, but omits the 'r' in front of the RE string.

     

    이 특별한 시퀀스를 사용할 때 기억해야 할 두 가지 미묘한 점이 있다. 첫째, 이는 Python의 문자열 리터럴과 정규식 시퀀스 간의 최악의 충돌이다. Python의 문자열 리터럴에서 \b는 백스페이스 문자, ASCII 값 8이다. 원시 문자열을 사용하지 않는 경우 Python은 \b를 백스페이스로 변환하므로 RE는 예상대로 일치하지 않는다. 다음 예는 이전 RE와 동일해 보이지만 RE 문자열 앞의 'r'을 생략한다.

    p = re.compile('\bclass\b')
    print(p.search('no class at all'))
    None
    print(p.search('\b' + 'class' + '\b'))
    <re.Match object; span=(0, 7), match='\x08class\x08'>

     

    Second, inside a character class, where there’s no use for this assertion, \b represents the backspace character, for compatibility with Python’s string literals.

     

    둘째, 이 어서션이 사용되지 않는 문자 클래스 내에서 \b는 Python의 문자열 리터럴과의 호환성을 위해 백스페이스 문자를 나타낸다.

     

    \B

    Another zero-width assertion, this is the opposite of \b, only matching when the current position is not at a word boundary.

     

    너비가 0인 또 다른 어서션이고 \b와 반대이며 현재 위치가 단어 경계에 있지 않을 때만 일치한다.

    Grouping

    Frequently you need to obtain more information than just whether the RE matched or not. Regular expressions are often used to dissect strings by writing a RE divided into several subgroups which match different components of interest. For example, an RFC-822 header line is divided into a header name and a value, separated by a ':', like this:

     

    RE가 일치하는지 여부보다 더 많은 정보를 얻어야 하는 경우가 많다. 정규식은 관심 있는 다양한 구성 요소와 일치하는 여러 하위 그룹으로 나누어진 RE를 작성하여 문자열을 분석하는 데 종종 사용된다. 예를 들어, RFC-822 헤더 행은 다음과 같이 ':'으로 구분된 헤더 이름과 값으로 구분된다.

    From: author@example.com
    User-Agent: Thunderbird 1.5.0.9 (X11/20061227)
    MIME-Version: 1.0
    To: editor@example.com

     

    This can be handled by writing a regular expression which matches an entire header line, and has one group which matches the header name, and another group which matches the header’s value.

    Groups are marked by the '(', ')' metacharacters. '(' and ')' have much the same meaning as they do in mathematical expressions; they group together the expressions contained inside them, and you can repeat the contents of a group with a quantifier, such as *, +, ?, or {m,n}. For example, (ab)* will match zero or more repetitions of ab.

     

    이는 전체 헤더 줄과 일치하고 헤더 이름과 일치하는 그룹 하나와 헤더 값과 일치하는 다른 그룹을 갖는 정규식을 작성하여 처리할 수 있다.

    그룹은 '(', ')' 메타 문자로 표시된다. '(' 및 ')'는 수학 표현식에서와 거의 동일한 의미를 갖는다. 내부에 포함된 표현식을 함께 그룹화하고 *, +, ? 또는 {m,n}과 같은 수량자를 사용하여 그룹의 내용을 반복할 수 있다. 예를 들어 (ab)*는 ab가 0개 이상 반복되는 경우와 일치한다.

    p = re.compile('(ab)*')
    print(p.match('ababababab').span())
    (0, 10)

     

    Groups indicated with '(', ')' also capture the starting and ending index of the text that they match; this can be retrieved by passing an argument to group(), start(), end(), and span(). Groups are numbered starting with 0. Group 0 is always present; it’s the whole RE, so match object methods all have group 0 as their default argument. Later we’ll see how to express groups that don’t capture the span of text that they match.

     

    '(', ')'로 표시된 그룹은 일치하는 텍스트의 시작 및 끝 인덱스도 캡처한다. 이는 group(), start(), end() 및span()에 인수를 전달하여 검색할 수 있다. 그룹은 0부터 시작하여 번호가 매겨진다. 그룹 0은 항상 존재한다. 전체 RE이므로 일치 개체 메서드는 모두 그룹 0을 기본 인수로 갖는다. 나중에 일치하는 텍스트 범위를 캡처하지 못하는 그룹을 표현하는 방법을 살펴본다.

    p = re.compile('(a)b')
    m = p.match('ab')
    m.group()
    'ab'
    m.group(0)
    'ab'

     

    Subgroups are numbered from left to right, from 1 upward. Groups can be nested; to determine the number, just count the opening parenthesis characters, going from left to right.

     

    하위 그룹은 왼쪽에서 오른쪽으로 1부터 위쪽으로 번호가 매겨진다. 그룹은 중첩될 수 있다. 숫자를 결정하려면 왼쪽에서 오른쪽으로 여는 괄호 문자를 세면 된다.

    p = re.compile('(a(b)c)d')
    m = p.match('abcd')
    m.group(0)
    'abcd'
    m.group(1)
    'abc'
    m.group(2)
    'b'

     

    group() can be passed multiple group numbers at a time, in which case it will return a tuple containing the corresponding values for those groups.

     

    group()은 한 번에 여러 그룹 번호를 전달할 수 있으며, 이 경우 해당 그룹에 해당하는 값을 포함하는 튜플을 반환한다.

    m.group(2,1,2)
    ('b', 'abc', 'b')

     

    The groups() method returns a tuple containing the strings for all the subgroups, from 1 up to however many there are.

     

    groups() 메서드는 1개부터 개수에 관계없이 모든 하위 그룹에 대한 문자열을 포함하는 튜플을 반환한다.

    m.groups()
    ('abc', 'b')

     

    Backreferences in a pattern allow you to specify that the contents of an earlier capturing group must also be found at the current location in the string. For example, \1 will succeed if the exact contents of group 1 can be found at the current position, and fails otherwise. Remember that Python’s string literals also use a backslash followed by numbers to allow including arbitrary characters in a string, so be sure to use a raw string when incorporating backreferences in a RE.

    For example, the following RE detects doubled words in a string.

     

    패턴의 역참조를 사용하면 이전 캡처 그룹의 콘텐츠도 문자열의 현재 위치에서 찾을 수 있도록 지정할 수 있다. 예를 들어, 그룹 1의 정확한 내용을 현재 위치에서 찾을 수 있으면 \1은 성공하고 그렇지 않으면 실패한다. Python의 문자열 리터럴은 백슬래시와 숫자를 사용하여 문자열에 임의의 문자를 포함할 수 있으므로 RE에 역참조를 통합할 때 원시 문자열을 사용해야 한다는 점을 기억한다.

    예를 들어 다음 RE는 문자열에서 이중 단어를 감지한다.

    p = re.compile(r'\b(\w+)\s+\1\b')
    p.search('Paris in the the spring').group()
    'the the'

     

    Backreferences like this aren’t often useful for just searching through a string — there are few text formats which repeat data in this way — but you’ll soon find out that they’re very useful when performing string substitutions.

     

    이와 같은 역참조는 단순히 문자열을 검색하는 데에는 유용하지 않다. 이러한 방식으로 데이터를 반복하는 텍스트 형식은 거의 없다. 그러나 문자열 대체를 수행할 때 매우 유용하다는 것을 곧 알게 될 것이다.

    Non-capturing and Named Groups

    Elaborate REs may use many groups, both to capture substrings of interest, and to group and structure the RE itself. In complex REs, it becomes difficult to keep track of the group numbers. There are two features which help with this problem. Both of them use a common syntax for regular expression extensions, so we’ll look at that first.

    Perl 5 is well known for its powerful additions to standard regular expressions. For these new features the Perl developers couldn’t choose new single-keystroke metacharacters or new special sequences beginning with \ without making Perl’s regular expressions confusingly different from standard REs. If they chose & as a new metacharacter, for example, old expressions would be assuming that & was a regular character and wouldn’t have escaped it by writing \& or [&].

    The solution chosen by the Perl developers was to use (?...) as the extension syntax. ? immediately after a parenthesis was a syntax error because the ? would have nothing to repeat, so this didn’t introduce any compatibility problems. The characters immediately after the ? indicate what extension is being used, so (?=foo) is one thing (a positive lookahead assertion) and (?:foo) is something else (a non-capturing group containing the subexpression foo).

    Python supports several of Perl’s extensions and adds an extension syntax to Perl’s extension syntax. If the first character after the question mark is a P, you know that it’s an extension that’s specific to Python.

    Now that we’ve looked at the general extension syntax, we can return to the features that simplify working with groups in complex REs.

    Sometimes you’ll want to use a group to denote a part of a regular expression, but aren’t interested in retrieving the group’s contents. You can make this fact explicit by using a non-capturing group: (?:...), where you can replace the ... with any other regular expression.

     

    정교한 RE는 관심 있는 하위 문자열을 캡처하고 RE 자체를 그룹화하고 구조화하기 위해 많은 그룹을 사용할 수 있다. 복잡한 RE에서는 그룹 번호를 추적하기가 어려워집니다. 이 문제를 해결하는 데 도움이 되는 두 가지 기능이 있다. 둘 다 정규식 확장에 대한 공통 구문을 사용하므로 먼저 이를 살펴본다.

    Perl 5는 표준 정규식에 대한 강력한 추가 기능으로 잘 알려져 있다. 이러한 새로운 기능을 위해 Perl 개발자는 Perl의 정규식을 표준 RE와 혼란스럽게 다르게 만들지 않고서는 새로운 단일 키 입력 메타 문자나 \로 시작하는 새로운 특수 시퀀스를 선택할 수 없다. 예를 들어 &를 새로운 메타 문자로 선택한 경우 이전 표현식은 &가 일반 문자라고 가정하고 \& 또는 [&]를 사용해 이스케이프하지 않았을 것이다.

    Perl 개발자가 선택한 솔루션은 (?...)를 확장 구문으로 사용하는 것이었다. 괄호 바로 뒤의 ?는 ?가 반복할 내용이 없으므로 구문 오류가 발생한다. 그래서 호환성 문제가 발생하지 않는다. ? 바로 뒤의 문자는 어떤 확장이 사용되고 있는지 나타내므로 (?=foo)는 하나(긍정적 예측 어서션)이고 (?:foo)는 다른 것(하위 표현식 foo를 포함하는 비캡처 그룹)이다.

    Python은 Perl의 여러 확장을 지원하고 Perl의 확장 구문에 확장 구문을 추가한다. 물음표 뒤의 첫 번째 문자가 P이면 Python에만 해당되는 확장이라는 것을 알 수 있다.

    이제 일반 확장 구문을 살펴보았으므로 복잡한 RE의 그룹 작업을 단순화하는 기능으로 돌아갈 수 있다.

    때로는 정규식의 일부를 나타내기 위해 그룹을 사용하고 싶지만 그룹의 내용을 검색하는 데는 관심이 없을 수도 있다. 비캡처 그룹(?:...)을 사용하여 이 사실을 명시적으로 만들 수 있다. 여기서 ...를 다른 정규 표현식으로 바꿀 수 있다.

    m = re.match("([abc])+", "abc")
    m.groups()
    ('c',)
    m = re.match("(?:[abc])+", "abc")
    m.groups()
    ()

     

    Except for the fact that you can’t retrieve the contents of what the group matched, a non-capturing group behaves exactly the same as a capturing group; you can put anything inside it, repeat it with a repetition metacharacter such as *, and nest it within other groups (capturing or non-capturing). (?:...) is particularly useful when modifying an existing pattern, since you can add new groups without changing how all the other groups are numbered. It should be mentioned that there’s no performance difference in searching between capturing and non-capturing groups; neither form is any faster than the other.

    A more significant feature is named groups: instead of referring to them by numbers, groups can be referenced by a name.

    The syntax for a named group is one of the Python-specific extensions: (?P<name>...). name is, obviously, the name of the group. Named groups behave exactly like capturing groups, and additionally associate a name with a group. The match object methods that deal with capturing groups all accept either integers that refer to the group by number or strings that contain the desired group’s name. Named groups are still given numbers, so you can retrieve information about a group in two ways:

     

    그룹이 일치하는 내용을 검색할 수 없다는 점을 제외하면 비캡처 그룹은 캡처 그룹과 정확히 동일하게 동작한다. 그 안에 무엇이든 넣을 수 있고, *와 같은 반복 메타 문자로 반복할 수 있으며, 다른 그룹(캡처 또는 비캡처) 내에 중첩할 수 있다. (?:...)는 다른 모든 그룹의 번호 지정 방식을 변경하지 않고도 새 그룹을 추가할 수 있으므로 기존 패턴을 수정할 때 특히 유용하다. 캡처하는 그룹과 캡처하지 않는 그룹 간의 검색에는 성능 차이가 없다는 점을 언급해야 한다. 어느 형태도 다른 형태보다 빠르지 않다.

    더 중요한 기능은 그룹이라는 이름이다. 그룹을 숫자로 참조하는 대신 이름으로 그룹을 참조할 수 있다.

    명명된 그룹의 구문은 Python 관련 확장 중 하나이다: (?P<name>...). name은 당연히 그룹의 이름이다. 명명된 그룹은 캡처 그룹과 똑같이 동작하며 추가로 이름을 그룹과 연결한다. 캡처 그룹을 처리하는 일치 개체 메서드는 모두 숫자로 그룹을 참조하는 정수 또는 원하는 그룹의 이름이 포함된 문자열을 허용한다. 이름이 지정된 그룹에는 여전히 번호가 부여되므로 다음 두 가지 방법으로 그룹에 대한 정보를 검색할 수 있다.

    p = re.compile(r'(?P<word>\b\w+\b)')
    m = p.search( '(((( Lots of punctuation )))' )
    m.group('word')
    'Lots'
    m.group(1)
    'Lots'

     

    Additionally, you can retrieve named groups as a dictionary with groupdict():

     

    또한 groupdict()를 사용하여 명명된 그룹을 dictionary로 검색할 수 있다.

    m = re.match(r'(?P<first>\w+) (?P<last>\w+)', 'Jane Doe')
    m.groupdict()
    {'first': 'Jane', 'last': 'Doe'}

     

    Named groups are handy because they let you use easily remembered names, instead of having to remember numbers. Here’s an example RE from the imaplib module:

     

    이름이 지정된 그룹을 사용하면 숫자를 기억할 필요 없이 쉽게 기억할 수 있는 이름을 사용할 수 있으므로 편리하다. 다음은 imaplib 모듈의 RE 예시이다:

    InternalDate = re.compile(r'INTERNALDATE "'
        r'(?P<day>[ 123][0-9])-(?P<mon>[A-Z][a-z][a-z])-'
        r'(?P<year>[0-9][0-9][0-9][0-9])'
        r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])'
        r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])'
        r'"')

     

    It’s obviously much easier to retrieve m.group('zonem'), instead of having to remember to retrieve group 9.

    The syntax for backreferences in an expression such as (...)\1 refers to the number of the group. There’s naturally a variant that uses the group name instead of the number. This is another Python extension: (?P=name) indicates that the contents of the group called name should again be matched at the current point. The regular expression for finding doubled words, \b(\w+)\s+\1\b can also be written as \b(?P<word>\w+)\s+(?P=word)\b:

     

    그룹 9를 검색하는 것을 기억하는 대신 m.group('zonem')을 검색하는 것이 훨씬 쉽다.

    (...)\1과 같은 표현식의 역참조 구문은 그룹 번호를 나타낸다. 당연히 번호 대신 그룹 이름을 사용하는 변형이 있다. 이것은 또 다른 Python 확장이다. (?P=name)은 name이라는 그룹의 내용이 현재 지점에서 다시 일치해야 함을 나타낸다. 이중 단어를 찾기 위한 정규식 \b(\w+)\s+\1\b\b(?P<word>\w+)\s+(?P=word)\b로 작성할 수도 있다.

    p = re.compile(r'\b(?P<word>\w+)\s+(?P=word)\b')
    p.search('Paris in the the spring').group()
    'the the'

    Lookahead Assertions

    Another zero-width assertion is the lookahead assertion. Lookahead assertions are available in both positive and negative form, and look like this:

     

    너비가 0인 또 다른 어서션은 예측 어서션이다. Lookahead 어서션은 긍정적인 형태와 부정적인 형태 모두에서 사용할 수 있으며 다음과 같다.


    (?=...)

    Positive lookahead assertion. This succeeds if the contained regular expression, represented here by ..., successfully matches at the current location, and fails otherwise. But, once the contained expression has been tried, the matching engine doesn’t advance at all; the rest of the pattern is tried right where the assertion started.

     

    긍정적인 예측 어서션. 여기에 ...로 표시된 포함된 정규식이 현재 위치에서 성공적으로 일치하면 성공하고 그렇지 않으면 실패한다. 그러나 일단 포함된 표현식이 시도되면 일치 엔진은 전혀 전진하지 않는다. 패턴의 나머지 부분은 어서션이 바로 시작된 곳에서 시도된다.

     

    (?!...)

    Negative lookahead assertion. This is the opposite of the positive assertion; it succeeds if the contained expression doesn’t match at the current position in the string.

     

    부정적인 예측 어서션이다. 이는 긍정적인 주장과 정반대이다. 포함된 표현식이 문자열의 현재 위치에서 일치하지 않으면 성공한다.


     

    To make this concrete, let’s look at a case where a lookahead is useful. Consider a simple pattern to match a filename and split it apart into a base name and an extension, separated by a .. For example, in news.rc, news is the base name, and rc is the filename’s extension.

    The pattern to match this is quite simple:

     

    이를 구체적으로 설명하기 위해 미리보기가 유용한 경우를 살펴본다. 파일 이름을 일치시키고 .로 구분된 기본 이름과 확장자로 분할하는 간단한 패턴을 고려한다. 예를 들어 news.rc에서 news는 기본 이름이고 rc는 파일 이름의 확장자이다.

    이에 맞는 패턴은 매우 간단한다.

     

    .*[.].*$

    Notice that the . needs to be treated specially because it’s a metacharacter, so it’s inside a character class to only match that specific character. Also notice the trailing $; this is added to ensure that all the rest of the string must be included in the extension. This regular expression matches foo.bar and autoexec.bat and sendmail.cf and printers.conf.

    Now, consider complicating the problem a bit; what if you want to match filenames where the extension is not bat? Some incorrect attempts:

    .*[.][^b].*$ The first attempt above tries to exclude bat by requiring that the first character of the extension is not a b. This is wrong, because the pattern also doesn’t match foo.bar.

     

    .은 메타 문자이기 때문에 특별히 처리해야 하므로 해당 특정 문자와만 일치하도록 문자 클래스 내에 있다. 또한 후행 $; 이는 문자열의 나머지 부분이 모두 확장에 포함되도록 하기 위해 추가된다. 이 정규식은 foo.bar, autoexec.bat, sendmail.cf 및 Printers.conf와 일치한다.

    이제 문제를 좀 더 복잡하게 만드는 것을 고려해 본다. 확장자가 bat이 아닌 파일 이름을 일치시키려면 어떻게 해야 하는가? 일부 잘못된 시도는:

    .*[.][^b].*$ 위의 첫 번째 시도에서는 확장자의 첫 번째 문자가 b가 아니도록 요구하여 bat을 제외하려고 시도한다. 패턴도 foo.bar와 일치하지 않기 때문에 이것은 잘못된 것이다.

     

    .*[.]([^b]..|.[^a].|..[^t])$

    The expression gets messier when you try to patch up the first solution by requiring one of the following cases to match: the first character of the extension isn’t b; the second character isn’t a; or the third character isn’t t. This accepts foo.bar and rejects autoexec.bat, but it requires a three-letter extension and won’t accept a filename with a two-letter extension such as sendmail.cf. We’ll complicate the pattern again in an effort to fix it.

     

    다음 사례 중 하나가 일치하도록 요구하여 첫 번째 솔루션을 패치하려고 하면 표현식이 더 복잡해진다. 확장의 첫 번째 문자는 b가 아니다. 두 번째 문자는 a가 아니다. 또는 세 번째 문자는 t가 아니다. 이는 foo.bar를 허용하고 autoexec.bat를 거부하지만 세 글자 확장자가 필요하며 sendmail.cf와 같은 두 글자 확장자를 가진 파일 이름은 허용되지 않는다. 문제를 해결하기 위해 패턴을 다시 복잡하게 만들 것이다.

     

    .*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$

    In the third attempt, the second and third letters are all made optional in order to allow matching extensions shorter than three characters, such as sendmail.cf.

    The pattern’s getting really complicated now, which makes it hard to read and understand. Worse, if the problem changes and you want to exclude both bat and exe as extensions, the pattern would get even more complicated and confusing.

    A negative lookahead cuts through all this confusion:

    .*[.](?!bat$)[^.]*$ The negative lookahead means: if the expression bat doesn’t match at this point, try the rest of the pattern; if bat$ does match, the whole pattern will fail. The trailing $ is required to ensure that something like sample.batch, where the extension only starts with bat, will be allowed. The [^.]* makes sure that the pattern works when there are multiple dots in the filename.

    Excluding another filename extension is now easy; simply add it as an alternative inside the assertion. The following pattern excludes filenames that end in either bat or exe:

     

    세 번째 시도에서는 sendmail.cf와 같이 3자보다 짧은 일치 확장자를 허용하기 위해 두 번째와 세 번째 문자를 모두 선택 사항으로 만든다.

    이제 패턴이 정말 복잡해지고 있어 읽고 이해하기가 어렵다. 더 나쁜 것은 문제가 변경되어 확장명으로 bat 및 exe를 모두 제외하려는 경우 패턴이 훨씬 더 복잡하고 혼란스러워질 수 있다는 것이다.

    부정적인 예측은 이 모든 혼란을 없애준다.

    .*[.](?!bat$)[^.]*$ 부정 예측은 다음을 의미한다. 이 시점에서 표현 bat가 일치하지 않으면 나머지 패턴을 시도한다. bat$이 일치하면 전체 패턴이 실패한다. 확장자가 bat로만 시작하는 Sample.batch와 같은 것을 허용하려면 후행 $가 필요하다. [^.]*는 파일 이름에 점이 여러 개 있을 때 패턴이 작동하는지 확인한다.

    이제 다른 파일 이름 확장자를 제외하는 것이 쉽다. 어서션 내부에 대안으로 추가하기만 하면 된다. 다음 패턴은 bat 또는 exe로 끝나는 파일 이름을 제외한다.

     

    .*[.](?!bat$|exe$)[^.]*$

    Modifying Strings

    Up to this point, we’ve simply performed searches against a static string. Regular expressions are also commonly used to modify strings in various ways, using the following pattern methods:

    Method/Attribute Purpose
    sub() Find all substrings where the RE matches, and replace them with a different string
    subn() Does the same thing as sub(), but returns the new string and the number of replacementsDoes the same thing as sub(), but returns the new string and the number of replacements

     

    지금까지 우리는 단순히 정적 문자열에 대해 검색을 수행했다. 정규 표현식은 일반적으로 다음 패턴 방법을 사용하여 다양한 방법으로 문자열을 수정하는 데 사용된다.

    방법/속성 목적
    sub() RE가 일치하는 모든 하위 문자열을 찾아 다른 문자열로 바꾼다.
    subn() sub()와 같은 일을 하지만 새 문자열과 대체 횟수를 반환한다. sub()와 같은 일을 하지만 새 문자열과 대체 횟수를 반환한다.

    Splitting Strings

    The split() method of a pattern splits a string apart wherever the RE matches, returning a list of the pieces. It’s similar to the split() method of strings but provides much more generality in the delimiters that you can split by; string split() only supports splitting by whitespace or by a fixed string. As you’d expect, there’s a module-level re.split() function, too.

     

    패턴의 Split() 메소드는 RE가 일치하는 곳마다 문자열을 분할하여 조각 목록을 반환한다. 이는 문자열의 Split() 메서드와 유사하지만 분할할 수 있는 구분 기호에 훨씬 더 많은 일반성을 제공한다. string Split()은 공백이나 고정 문자열에 의한 분할만 지원한다. 예상한 대로 모듈 수준 re.split() 함수도 있다.


    .split(string[, maxsplit=0])

    Split string by the matches of the regular expression. If capturing parentheses are used in the RE, then their contents will also be returned as part of the resulting list. If maxsplit is nonzero, at most maxsplit splits are performed.

     

    정규식 일치 항목으로 문자열을 분할한다. RE에서 캡처 괄호를 사용하는 경우 해당 내용도 결과 목록의 일부로 반환된다. maxsplit이 0이 아닌 경우 최대 maxsplit 분할이 수행된다.


     

    You can limit the number of splits made, by passing a value for maxsplit. When maxsplit is nonzero, at most maxsplit splits will be made, and the remainder of the string is returned as the final element of the list. In the following example, the delimiter is any sequence of non-alphanumeric characters.

     

    maxsplit 값을 전달하여 분할 수를 제한할 수 있다. maxsplit이 0이 아닌 경우 최대 maxsplit 분할이 수행되고 문자열의 나머지 부분이 목록의 최종 요소로 반환된다. 다음 예에서 구분 기호는 영숫자가 아닌 문자의 시퀀스이다.

    p = re.compile(r'\W+')
    p.split('This is a test, short and sweet, of split().')
    ['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', '']
    p.split('This is a test, short and sweet, of split().', 3)
    ['This', 'is', 'a', 'test, short and sweet, of split().']

     

    Sometimes you’re not only interested in what the text between delimiters is, but also need to know what the delimiter was. If capturing parentheses are used in the RE, then their values are also returned as part of the list. Compare the following calls:

     

    때로는 구분 기호 사이의 텍스트가 무엇인지에 관심이 있을 뿐만 아니라 구분 기호가 무엇인지 알아야 할 때도 있다. RE에서 캡처링 괄호가 사용되는 경우 해당 값도 목록의 일부로 반환된다. 다음 호출을 비교하라.

    p = re.compile(r'\W+')
    p2 = re.compile(r'(\W+)')
    p.split('This... is a test.')
    ['This', 'is', 'a', 'test', '']
    p2.split('This... is a test.')
    ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']

     

    The module-level function re.split() adds the RE to be used as the first argument, but is otherwise the same.

     

    모듈 수준 함수 re.split()은 첫 번째 인수로 사용할 RE를 추가하지만 그 외에는 동일하다.

    re.split(r'[\W]+', 'Words, words, words.')
    ['Words', 'words', 'words', '']
    re.split(r'([\W]+)', 'Words, words, words.')
    ['Words', ', ', 'words', ', ', 'words', '.', '']
    re.split(r'[\W]+', 'Words, words, words.', 1)
    ['Words', 'words, words.']

    Search and Replace

    Another common task is to find all the matches for a pattern, and replace them with a different string. The sub() method takes a replacement value, which can be either a string or a function, and the string to be processed.

     

    또 다른 일반적인 작업은 패턴과 일치하는 항목을 모두 찾아 다른 문자열로 바꾸는 것이다. sub() 메소드는 문자열 또는 함수일 수 있는 대체 값과 처리할 문자열을 사용한다.


    .sub(replacement, string[, count=0])

    Returns the string obtained by replacing the leftmost non-overlapping occurrences of the RE in string by the replacement replacement. If the pattern isn’t found, string is returned unchanged.

    The optional argument count is the maximum number of pattern occurrences to be replaced; count must be a non-negative integer. The default value of 0 means to replace all occurrences.

     

    문자열에서 가장 왼쪽의 겹치지 않는 RE 항목을 대체 대체 항목으로 대체하여 얻은 문자열을 반환한다. 패턴을 찾을 수 없으면 문자열이 변경되지 않고 반환된다.

    선택적 인수 count는 대체될 패턴 발생의 최대 수이다. count는 음수가 아닌 정수여야 한다. 기본값 0은 모든 항목을 바꾸는 것을 의미한다.


     

    Here’s a simple example of using the sub() method. It replaces colour names with the word colour:

     

    다음은 sub() 메서드를 사용하는 간단한 예이다. 색상 이름을 colour라는 단어로 바꾼다.

    p = re.compile('(blue|white|red)')
    p.sub('colour', 'blue socks and red shoes')
    'colour socks and colour shoes'
    p.sub('colour', 'blue socks and red shoes', count=1)
    'colour socks and red shoes'

     

    The subn() method does the same work, but returns a 2-tuple containing the new string value and the number of replacements that were performed:

     

    subn() 메서드는 동일한 작업을 수행하지만 새 문자열 값과 수행된 대체 횟수를 포함하는 2-튜플을 반환한다.

    p = re.compile('(blue|white|red)')
    p.subn('colour', 'blue socks and red shoes')
    ('colour socks and colour shoes', 2)
    p.subn('colour', 'no colours at all')
    ('no colours at all', 0)

     

    Empty matches are replaced only when they’re not adjacent to a previous empty match.

     

    빈 일치 항목은 이전의 빈 일치 항목과 인접하지 않은 경우에만 대체된다.

    p = re.compile('x*')
    p.sub('-', 'abxd')
    '-a-b--d-'

     

    If replacement is a string, any backslash escapes in it are processed. That is, \n is converted to a single newline character, \r is converted to a carriage return, and so forth. Unknown escapes such as \& are left alone. Backreferences, such as \6, are replaced with the substring matched by the corresponding group in the RE. This lets you incorporate portions of the original text in the resulting replacement string.

    This example matches the word section followed by a string enclosed in {, }, and changes section to subsection:

     

    replacement가 문자열인 경우 해당 문자열에 포함된 모든 백슬래시 이스케이프가 처리된다. 즉, \n은 단일 개행 문자로 변환되고, \r은 캐리지 리턴으로 변환되는 식이다. \&와 같은 알 수 없는 이스케이프는 그대로 유지된다. \6과 같은 역참조는 RE의 해당 그룹과 일치하는 하위 문자열로 대체된다. 이를 통해 결과 대체 문자열에 원본 텍스트의 일부를 통합할 수 있다.

    이 예에서는 단어 section과 그 뒤에 {, }로 묶인 문자열을 일치시키고 section을 subsection으로 변경한다.

    p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
    p.sub(r'subsection{\1}','section{First} section{second}')
    'subsection{First} subsection{second}'

     

    There’s also a syntax for referring to named groups as defined by the (?P<name>...) syntax. \g<name> will use the substring matched by the group named name, and \g<number> uses the corresponding group number. \g<2> is therefore equivalent to \2, but isn’t ambiguous in a replacement string such as \g<2>0. (\20 would be interpreted as a reference to group 20, not a reference to group 2 followed by the literal character '0'.) The following substitutions are all equivalent, but use all three variations of the replacement string.

     

    (?P<name>...) 구문으로 정의된 대로 명명된 그룹을 참조하기 위한 구문도 있다. \g<name>은 name이라는 그룹과 일치하는 하위 문자열을 사용하고, \g<number>는 해당 그룹 번호를 사용한다. 따라서 \g<2>\2와 동일하지만 \g<2>0과 같은 대체 문자열에서는 모호하지 않다. (\20은 리터럴 문자 '0'이 뒤따르는 그룹 2에 대한 참조가 아니라 그룹 20에 대한 참조로 해석된다.) 다음 대체는 모두 동일하지만 대체 문자열의 세 가지 변형을 모두 사용한다.

    p = re.compile('section{ (?P<name> [^}]* ) }', re.VERBOSE)
    p.sub(r'subsection{\1}','section{First}')
    'subsection{First}'
    p.sub(r'subsection{\g<1>}','section{First}')
    'subsection{First}'
    p.sub(r'subsection{\g<name>}','section{First}')
    'subsection{First}'

     

    replacement can also be a function, which gives you even more control. If replacement is a function, the function is called for every non-overlapping occurrence of pattern. On each call, the function is passed a match object argument for the match and can use this information to compute the desired replacement string and return it.

    In the following example, the replacement function translates decimals into hexadecimal:

     

    대체는 함수가 될 수도 있으며 이를 통해 더 많은 제어가 가능하다. 대체가 함수인 경우 패턴이 겹치지 않을 때마다 함수가 호출된다. 각 호출에서 함수는 일치 항목에 대한 일치 개체 인수를 전달하고 이 정보를 사용하여 원하는 대체 문자열을 계산하고 반환할 수 있다.

    다음 예에서 대체 함수는 10진수를 16진수로 변환한다.

    def hexrepl(match):
            "Return the hex string for a decimal number"
        value = int(match.group())
        return hex(value)
    p = re.compile(r'\d+')
    p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
    'Call 0xffd2 for printing, 0xc000 for user code.'

     

    When using the module-level re.sub() function, the pattern is passed as the first argument. The pattern may be provided as an object or as a string; if you need to specify regular expression flags, you must either use a pattern object as the first parameter, or use embedded modifiers in the pattern string, e.g. sub("(?i)b+", "x", "bbbb BBBB") returns 'x x'.

     

    모듈 수준 re.sub() 함수를 사용할 때 패턴이 첫 번째 인수로 전달된다. 패턴은 객체 또는 문자열로 제공될 수 있다. 정규식 플래그를 지정해야 하는 경우 패턴 개체를 첫 번째 매개변수로 사용하거나 패턴 문자열에 포함된 수정자를 사용해야 한다. sub("(?i)b+", "x", "bbbb BBBB")는 'x x'를 반환한다.

    Common Problems

    Regular expressions are a powerful tool for some applications, but in some ways their behaviour isn’t intuitive and at times they don’t behave the way you may expect them to. This section will point out some of the most common pitfalls.

     

    정규식은 일부 응용 프로그램에 대한 강력한 도구이지만 어떤 면에서는 동작이 직관적이지 않고 때로는 예상한 대로 동작하지 않는다. 이 섹션에서는 가장 일반적인 함정 중 일부를 지적한다.

    Use String Methods

    Sometimes using the re module is a mistake. If you’re matching a fixed string, or a single character class, and you’re not using any re features such as the IGNORECASE flag, then the full power of regular expressions may not be required. Strings have several methods for performing operations with fixed strings and they’re usually much faster, because the implementation is a single small C loop that’s been optimized for the purpose, instead of the large, more generalized regular expression engine.

    One example might be replacing a single fixed string with another one; for example, you might replace word with deed. re.sub() seems like the function to use for this, but consider the replace() method. Note that replace() will also replace word inside words, turning swordfish into sdeedfish, but the naive RE word would have done that, too. (To avoid performing the substitution on parts of words, the pattern would have to be \bword\b, in order to require that word have a word boundary on either side. This takes the job beyond replace()’s abilities.)

    Another common task is deleting every occurrence of a single character from a string or replacing it with another single character. You might do this with something like re.sub('\n', ' ', S), but translate() is capable of doing both tasks and will be faster than any regular expression operation can be.

    In short, before turning to the re module, consider whether your problem can be solved with a faster and simpler string method.

     

    때로는 re 모듈을 사용하는 것이 실수이다. 고정 문자열이나 단일 문자 클래스를 일치시키고 IGNORECASE 플래그와 같은 re 기능을 사용하지 않는 경우 정규식의 모든 기능이 필요하지 않을 수 있다. 문자열에는 고정 문자열로 작업을 수행하는 여러 가지 방법이 있으며 구현은 크고 일반화된 정규식 엔진 대신 목적에 맞게 최적화된 단일 작은 C 루프이기 때문에 일반적으로 훨씬 빠르다.

    한 가지 예는 단일 고정 문자열을 다른 문자열로 바꾸는 것이다. 예를 들어, word를 deed로 바꿀 수 있다. re.sub()는 이를 위해 사용하는 함수처럼 보이지만, replacement() 메소드를 고려한다. replacement()는 단어 안의 단어도 대체하여 swordfish를 sdeedfish로 바꾸지만 순진한 RE 단어도 그렇게 했을 것이다. (word 부분에 대한 대체를 수행하지 않으려면 해당 word가 양쪽에 word 경계를 갖도록 요구하기 위해 패턴은 \bword\b여야 한다. 이는 replace()의 능력을 넘어서는 작업을 수행한다.)

    또 다른 일반적인 작업은 문자열에서 단일 문자를 모두 삭제하거나 다른 단일 문자로 바꾸는 것이다. re.sub('\n', ' ', S)와 같은 방법으로 이 작업을 수행할 수 있지만,translate()는 두 작업을 모두 수행할 수 있으며 정규 표현식 작업보다 빠르다.

    즉, re 모듈을 사용하기 전에 더 빠르고 간단한 문자열 방법으로 문제를 해결할 수 있는지 고려한다.

    match() versus search()

    The match() function only checks if the RE matches at the beginning of the string while search() will scan forward through the string for a match. It’s important to keep this distinction in mind. Remember, match() will only report a successful match which will start at 0; if the match wouldn’t start at zero, match() will not report it.

     

    match() 함수는 RE가 문자열의 시작 부분에서 일치하는지 확인하는 반면 search()는 일치하는 문자열을 통해 앞으로 스캔한다. 이 차이점을 염두에 두는 것이 중요한다. match()는 0에서 시작하는 성공적인 일치만 보고한다는 점을 기억한다. 일치가 0에서 시작하지 않으면 match()는 이를 보고하지 않는다.

    print(re.match('super', 'superstition').span())
    (0, 5)
    print(re.match('super', 'insuperable'))
    None

     

    On the other hand, search() will scan forward through the string, reporting the first match it finds.

     

    반면, search()는 문자열을 앞으로 스캔하여 찾은 첫 번째 일치 항목을 보고한다.

    print(re.search('super', 'superstition').span())
    (0, 5)
    print(re.search('super', 'insuperable').span())
    (2, 7)

     

    Sometimes you’ll be tempted to keep using re.match(), and just add .* to the front of your RE. Resist this temptation and use re.search() instead. The regular expression compiler does some analysis of REs in order to speed up the process of looking for a match. One such analysis figures out what the first character of a match must be; for example, a pattern starting with Crow must match starting with a 'C'. The analysis lets the engine quickly scan through the string looking for the starting character, only trying the full match if a 'C' is found.

    Adding .* defeats this optimization, requiring scanning to the end of the string and then backtracking to find a match for the rest of the RE. Use re.search() instead.

     

    때때로 re.match()를 계속 사용하고 RE 앞에 .*를 추가하고 싶은 유혹을 받을 수도 있다. 이러한 유혹에 저항하고 대신 re.search()를 사용한다. 정규식 컴파일러는 일치 항목을 찾는 프로세스의 속도를 높이기 위해 RE에 대한 일부 분석을 수행한다. 그러한 분석 중 하나는 일치 항목의 첫 번째 문자가 무엇인지 파악한다. 예를 들어 Crow로 시작하는 패턴은 'C'로 시작하는 것과 일치해야 한다. 분석을 통해 엔진은 시작 문자를 찾기 위해 문자열을 빠르게 스캔하고 'C'가 발견된 경우에만 전체 일치를 시도한다.

    .*를 추가하면 이 최적화가 실패하므로 문자열 끝까지 검색한 다음 역추적하여 나머지 RE와 일치하는 항목을 찾아야 한다. 대신 re.search()를 사용한다.

    Greedy versus Non-Greedy

    When repeating a regular expression, as in a*, the resulting action is to consume as much of the pattern as possible. This fact often bites you when you’re trying to match a pair of balanced delimiters, such as the angle brackets surrounding an HTML tag. The naive pattern for matching a single HTML tag doesn’t work because of the greedy nature of .*.

     

    a*와 같이 정규식을 반복할 때 결과 작업은 가능한 한 많은 패턴을 사용하는 것이다. 이 사실은 HTML 태그를 둘러싼 꺾쇠 괄호와 같이 균형 잡힌 구분 기호 쌍을 일치시키려고 할 때 종종 당황스럽다. 단일 HTML 태그를 일치시키는 순진한 패턴은 .*의 욕심 많은 특성 때문에 작동하지 않는다.

    s = '<html><head><title>Title</title>'
        len(s)
    32
    print(re.match('<.*>', s).span())
    (0, 32)
    print(re.match('<.*>', s).group())
    <html><head><title>Title</title>

     

    The RE matches the '<' in '<html>', and the .* consumes the rest of the string. There’s still more left in the RE, though, and the > can’t match at the end of the string, so the regular expression engine has to backtrack character by character until it finds a match for the >. The final match extends from the '<' in '<html>' to the '>' in '</title>', which isn’t what you want.

    In this case, the solution is to use the non-greedy quantifiers *?, +?, ??, or {m,n}?, which match as little text as possible. In the above example, the '>' is tried immediately after the first '<' matches, and when it fails, the engine advances a character at a time, retrying the '>' at every step. This produces just the right result:

     

    RE는 '<html>'의 '<'와 일치하고 .*는 문자열의 나머지 부분을 사용한다. 하지만 RE에는 아직 더 많은 것이 남아 있고 >는 문자열 끝에서 일치할 수 없으므로 정규식 엔진은 >에 대한 일치를 찾을 때까지 문자별로 역추적해야 한다. 최종 일치는 '<html>'의 '<'에서 '</title>'의 '>'까지 확장되는데 이는 원하는 것과 다르다.

    이 경우 해결책은 가능한 한 적은 양의 텍스트와 일치하는 탐욕스럽지 않은 수량자 *?, +?, ?? 또는 {m,n}?를 사용하는 것이다. 위의 예에서 '>'는 첫 번째 '<' 일치 직후에 시도되고, 실패할 경우 엔진은 한 번에 한 문자씩 앞으로 나아가며 모든 단계에서 '>'를 다시 시도한다. 이렇게 하면 올바른 결과가 생성된다.

    print(re.match('<.*?>', s).group())
    <html>

     

    (Note that parsing HTML or XML with regular expressions is painful. Quick-and-dirty patterns will handle common cases, but HTML and XML have special cases that will break the obvious regular expression; by the time you’ve written a regular expression that handles all of the possible cases, the patterns will be very complicated. Use an HTML or XML parser module for such tasks.)

     

    (정규식으로 HTML 또는 XML을 구문 분석하는 것은 고통스럽다. Quick-and-dirty 패턴은 일반적인 경우를 처리하지만 HTML과 XML에는 명백한 정규식을 깨뜨리는 특수한 경우가 있다. 가능한 모든 경우를 처리하려면 패턴이 매우 복잡하므로 이러한 작업에는 HTML 또는 XML 파서 모듈을 사용한다.)

    Using re.VERBOSE

    By now you’ve probably noticed that regular expressions are a very compact notation, but they’re not terribly readable. REs of moderate complexity can become lengthy collections of backslashes, parentheses, and metacharacters, making them difficult to read and understand.

    For such REs, specifying the re.VERBOSE flag when compiling the regular expression can be helpful, because it allows you to format the regular expression more clearly.

    The re.VERBOSE flag has several effects. Whitespace in the regular expression that isn’t inside a character class is ignored. This means that an expression such as dog | cat is equivalent to the less readable dog|cat, but [a b] will still match the characters 'a', 'b', or a space. In addition, you can also put comments inside a RE; comments extend from a # character to the next newline. When used with triple-quoted strings, this enables REs to be formatted more neatly:

     

    지금쯤이면 정규 표현식이 매우 간결한 표기법이지만 읽기가 쉽지 않다는 것을 눈치챘을 것이다. 중간 정도의 복잡성을 지닌 RE는 백슬래시, 괄호, 메타 문자로 구성된 긴 모음이 되어 읽고 이해하기 어려울 수 있다.

    이러한 RE의 경우 정규식을 컴파일할 때 re.VERBOSE 플래그를 지정하면 정규식의 형식을 더 명확하게 지정할 수 있으므로 도움이 될 수 있다.

    re.VERBOSE 플래그에는 여러 가지 효과가 있다. 문자 클래스 내부에 없는 정규식의 공백은 무시된다. 이는 dog | cat은 읽기 어려운 dog|cat와 동일하지만 [a b]는 여전히 문자 'a', 'b' 또는 공백과 일치한다. 또한 RE 내부에 주석을 넣을 수도 있다. 주석은 # 문자부터 다음 줄 바꿈까지 확장된다. 삼중따옴표로 묶인 문자열과 함께 사용하면 RE 형식을 더욱 깔끔하게 지정할 수 있다.

    pat = re.compile(r"""
        \s*                 # Skip leading whitespace
        (?P<header>[^:]+)   # Header name
        \s* :               # Whitespace, and a colon
        (?P<value>.*?)      # The header's value -- *? used to
        # lose the following trailing whitespace
        \s*$                # Trailing whitespace to end-of-line
    """, re.VERBOSE)

     

    This is far more readable than:

     

    이는 다음보다 훨씬 더 읽기 쉽다.

    pat = re.compile(r"\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$")

    Feedback

    Regular expressions are a complicated topic. Did this document help you understand them? Were there parts that were unclear, or Problems you encountered that weren’t covered here? If so, please send suggestions for improvements to the author.

    The most complete book on regular expressions is almost certainly Jeffrey Friedl’s Mastering Regular Expressions, published by O’Reilly. Unfortunately, it exclusively concentrates on Perl and Java’s flavours of regular expressions, and doesn’t contain any Python material at all, so it won’t be useful as a reference for programming in Python. (The first edition covered Python’s now-removed regex module, which won’t help you much.) Consider checking it out from your library.

     

    정규식은 복잡한 주제이다. 이 문서가 이해하는 데 도움이 되었는가? 불분명한 부분이나 여기서 다루지 않은 문제가 있었다면 작성자에게 개선 제안을 보낸다.

    정규식에 관한 가장 완벽한 책은 거의 확실하게 O'Reilly에서 출판된 Jeffrey Friedl의 Mastering Regular Expressions이다. 불행하게도 이 책은 Perl과 Java의 정규 표현식에만 집중하고 Python 자료를 전혀 포함하지 않으므로 Python 프로그래밍에 대한 참고 자료로는 유용하지 않다. (첫 번째 판에서는 현재 제거된 Python의 정규식 모듈을 다루었지만 별로 도움이 되지 않는다.) 라이브러리에서 확인해 본다.

    728x90

    댓글

Designed by Tistory.