Perl 정규표현식 문자 클래스

Perl 정규표현식 문자 클래스 (perlrecharclass)

Perl 정규표현식에서 문자 클래스의 문법과 사용을 다루는 매뉴얼 페이지예요. Perl 정규표현식에 대한 최상위 문서는 perlre예요.

출처: Perl 공식 문서 - perlrecharclass

본문

설명 (DESCRIPTION)

문자 클래스는 문자 집합을 표기하는 방식으로, 집합의 문자가 매치되게 해요. 여기서 중요한 걸 기억하세요: 문자 클래스를 매치하면 소스 문자열에서 정확히 한 문자를 소비해요. (소스 문자열은 정규식이 매치되는 대상 문자열이에요.)

Perl 정규표현식에는 세 가지 유형의 문자 클래스가 있어요: 점(dot), 백슬래시 시퀀스, 대괄호로 감싼 형태. 다만 "문자 클래스"라는 용어가 보통 대괄호 형태만을 가리키는 데 쓰인다는 점을 명심하세요. 확실히 대부분의 Perl 문서가 그렇게 해요.

점 (The dot)

점(또는 마침표) .는 아마 가장 많이 쓰이고, 확실히 가장 잘 알려진 문자 클래스예요. 기본적으로 점은 새 줄을 제외한 어떤 문자와도 매치해요. 그 기본값은 single line 수정자로 새 줄 매치를 추가하도록 바꿀 수 있어요: 정규식 전체는 /s 수정자로, 국소적으로는 (?s)로(그리고 use re '/s'의 범위 안에서 전역적으로도)요. (아래 설명할 "\N" 백슬래시 시퀀스는 single line 수정자와 무관하게 새 줄을 제외한 어떤 문자와도 매치해요.)

몇 가지 예시를 볼게요:

"a"  =~  /./       # Match
"."  =~  /./       # Match
""   =~  /./       # No match (dot has to match a character)
"\n" =~  /./       # No match (dot does not match a newline)
"\n" =~  /./s      # Match (global 'single line' modifier)
"\n" =~  /(?s:.)/  # Match (local 'single line' modifier)
"ab" =~  /^.$/     # No match (dot matches one character)

백슬래시 시퀀스 (Backslash sequences)

백슬래시 시퀀스는 문자들의 시퀀스로, 첫 번째가 백슬래시예요. Perl은 그런 많은 시퀀스에 특별한 의미를 부여하고, 그중 일부는 문자 클래스예요. 즉 각각 단일 문자에 매치하는데, 그 문자가 시퀀스가 정의한 특정 문자 집합에 속해야 해요.

다음은 문자 클래스인 백슬래시 시퀀스 목록이에요. 자세히는 아래에서 다뤄요. (문자 클래스가 아닌 백슬래시 시퀀스는 perlrebackslash를 보세요.)

\d             Match a decimal digit character.
\D             Match a non-decimal-digit character.
\w             Match a "word" character.
\W             Match a non-"word" character.
\s             Match a whitespace character.
\S             Match a non-whitespace character.
\h             Match a horizontal whitespace character.
\H             Match a character that isn't horizontal whitespace.
\v             Match a vertical whitespace character.
\V             Match a character that isn't vertical whitespace.
\N             Match a character that isn't a newline.
\pP, \p{Prop}  Match a character that has the given Unicode property.
\PP, \P{Prop}  Match a character that doesn't have the Unicode property

\N

v5.12부터 사용 가능한 \N은 점처럼 새 줄이 아닌 어떤 문자와도 매치해요. 차이는 \Nsingle line 정규표현식 수정자의 영향을 받지 않는다는 거예요(위 "The dot" 참조). \N{...} 형태는 완전히 다른 것을 의미할 수 있다는 점을 주의하세요. {...}수량자라면, 비-새 줄 문자를 그만큼 매치한다는 뜻이에요. 예를 들어 \N{3}은 비-새 줄 3개를 매치하라는 뜻이고, \N{5,}는 비-새 줄 5개 이상을 매치하라는 뜻이에요. 하지만 {...}가 합법적인 수량자가 아니라면 이름 붙은 문자로 간주돼요. charnames를 보세요. 예를 들어 \N{COLON}, \N{4F}, \N{F4} 중 어느 것도 합법적인 수량자를 포함하지 않으므로, Perl은 각각 이름이 COLON, 4F, F4인 문자를 찾으려 해요.

숫자 (Digits)

\d는 십진 숫자 로 간주되는 단일 문자에 매치해요. /a 정규표현식 수정자가 적용 중이면 [0-9]에 매치해요. 그렇지 않으면 \p{Digit}이 매치하는 무엇이든 매치하는데, 여기에는 [0-9]가 포함돼요. (드문 가능한 예외는 locale 매치 규칙 아래에서, 현재 locale이 \d로 매치되는 [0-9]를 갖지 못하고/하거나 코드 포인트가 256보다 작은 다른 문자를 매치할 수 있다는 거예요. 합법적인 유일한 그런 locale 정의는 [0-9]에 연속된 10자의 다른 숫자 집합을 더한 것을 매치하는 것일 텐데, 그 외는 C 언어 표준을 위반하지만 Perl은 현재 이에 대해 아무것도 가정하지 않아요.)

이것이 뜻하는 바는 /a 수정자가 적용 중이 아니면 \d가 숫자 '0'-'9'뿐 아니라 아랍어, 데바나가리, 다른 언어들의 숫자도 매치한다는 거예요. 이것은 혼란과 일부 보안 문제를 일으킬 수 있어요.

\d가 매치하는 일부 숫자는 [0-9]의 일부와 닮았지만 다른 값을 가져요. 예를 들어 BENGALI DIGIT FOUR(U+09EA)는 ASCII DIGIT EIGHT(U+0038)와 아주 닮았고, LEPCHA DIGIT SIX(U+1C46)는 ASCII DIGIT FIVE(U+0035)와 아주 닮았어요. ASCII 숫자만 기대하는 애플리케이션은 속을 수 있고, 매치가 \d+라면 매치된 문자열이 실제 의미하는 숫자와 다른 것을 의미하는 것처럼 보이는 서로 다른 문자 체계의 숫자 혼합을 포함할 수 있어요. "num()" in Unicode::UCD으로 값을 안전하게 계산할 수 있는데, 입력 문자열이 그런 혼합을 포함하면 undef를 반환해요. 그렇지 않으면, 예를 들어 표시된 가격이 보이는 것과 의도적으로 다를 수 있어요.

\p{Digit}(따라서 /a 수정자 밖의 \d)이 의미하는 것은 \p{General_Category=Decimal_Number} 또는 동의어로 \p{General_Category=Digit}이에요. Unicode 4.1부터 이것은 \p{Numeric_Type=Decimal}이 매치하는 것과 같은 문자 집합이에요. 하지만 Unicode는 비슷한 이름의 다른 속성 \p{Numeric_Type=Digit}도 있는데, 이것은 완전히 다른 문자 집합에 매치해요. 그 문자들은 CIRCLED DIGIT ONE이나 첨자 같은 것이거나, 숫자 10개가 모두 없는 문자 체계에서 온 것들이에요.

설계 의도는 \d가 "정상" big-endian 위치 십진 문법(예를 들어 123이 백 하나 + 십 둘 + 일 셋을 의미하는)에 안전하게 쓸 수 있는 문자 집합과 정확히 매치하도록 하는 거예요. 이 위치 표기법은 다른 유형의 "숫자" \p{Numeric_Type=Digit}에 매치하는 문자에는 반드시 적용되지 않으므로, \d는 그것들에 매치하지 않아요.

Tamil 숫자(U+0BE6 - U+0BEF)는 옛 스타일 Tamil 숫자에서도 합법적으로 쓸 수 있는데, 거기서는 "times 10", "times 100" 등을 의미하는 문자로 구분되어 한 번에 한 개 이상 나오지 않아요. (https://www.unicode.org/notes/tn21 참조.)

\d가 매치하지 않는 어떤 문자든 \D가 매치해요.

단어 문자 (Word characters)

\w는 단일 영숫자 문자(알파벳 문자 또는 십진 숫자), 또는 밑줄("_") 같은 연결 구두점 문자, 또는 그중 하나에 붙는 "mark" 문자(어떤 악센트 같은)에 매치해요. 전체 단어에는 매치하지 않아요. 전체 단어를 매치하려면 \w+를 쓰세요. 이것은 영어 단어를 매치하는 것과 같지 않지만, ASCII 범위에서는 Perl 식별자 문자의 문자열과 같아요.

/a 수정자가 적용 중이면 ...

\w는 63개 문자 [a-zA-Z0-9_]에 매치해요.

그렇지 않으면 ...

코드 포인트가 255보다 크면 ... \w는 이 범위에서 \p{Word}가 매치하는 것과 같아요. 즉 태국어 글자, 그리스어 글자 등에 매치해요. 이것은 두 단어를 연결하는 연결 구두점(밑줄 같은), 또는 COMBINING TILDE 같은 결합 구별 부호와, 글자에 보조 표시를 더하는 데 일반적으로 쓰이는 수식 글자를 포함해요.

코드 포인트가 256보다 작으면 ...

  • locale 규칙이 적용 중이면 ... \w는 플랫폼의 네이티브 밑줄 문자에 더해 locale이 영숫자로 간주하는 모든 것에 매치해요.
  • 대신 Unicode 규칙이 적용 중이면 ... \w\p{Word}가 매치하는 것과 정확히 매치해요.
  • 그렇지 않으면 ... \w는 [a-zA-Z0-9_]에 매치해요.

어떤 규칙이 적용되는지는 "Which character set modifier is in effect?" in perlre에 설명된 대로 결정돼요.

완전한 Unicode 단어 문자 목록에는 여러 보안 문제가 있어요. https://unicode.org/reports/tr36을 보세요.

또한 프로그래밍 언어 식별자에 있는, ASCII 범위를 넘는 더 세밀한 문자 집합을 위해 더 사용자화된 "Unicode Properties"인 \p{ID_Start}, \p{ID_Continue}, \p{XID_Start}, \p{XID_Continue}를 대신 쓰고 싶을 수도 있어요. https://unicode.org/reports/tr31을 보세요.

\w가 매치하지 않는 어떤 문자든 \W가 매치해요.

공백 (Whitespace)

\s는 공백으로 간주되는 어떤 단일 문자에 매치해요.

/a 수정자가 적용 중이면 ...

모든 Perl 버전에서 \s는 5개 문자 [\t\n\f\r ]에 매치해요. 즉 가로 탭, 새 줄, 폼 피드, 캐리지 리턴, 공백이에요. Perl v5.18부터는 세로 탭 \cK도 매치해요. 이에 대한 논의는 아래 주석 [1]을 보세요.

그렇지 않으면 ...

코드 포인트가 255보다 크면 ... \s는 아래 표에서 "s" 열로 표시된 255보다 큰 코드 포인트에 정확히 매치해요.

코드 포인트가 256보다 작으면 ...

  • locale 규칙이 적용 중이면 ... \s는 locale이 공백으로 간주하는 모든 것에 매치해요.
  • 대신 Unicode 규칙이 적용 중이면 ... \s는 아래 표에서 "s" 열로 표시된 문자에 정확히 매치해요.
  • 그렇지 않으면 ... \s는 [\t\n\f\r ]에 매치하고, Perl v5.18부터는 세로 탭 \cK에도 매치해요. (이 논의는 아래 주석 [1]을 보세요.) 이 목록이 비분리 공백(nbsp)을 포함하지 않는다는 점을 주의하세요.

어떤 규칙이 적용되는지는 "Which character set modifier is in effect?" in perlre에 설명된 대로 결정돼요.

\s가 매치하지 않는 어떤 문자든 \S가 매치해요.

\h는 가로 공백으로 간주되는 어떤 문자에 매치해요. 플랫폼의 공백·탭 문자와 아래 표에 나열된 다른 몇 개를 포함해요. \H는 가로 공백으로 간주되지 않는 어떤 문자에 매치해요. 이들은 플랫폼의 네이티브 문자 집합을 쓰고, 다른 곳에서 사용 중일 수 있는 어떤 locale도 고려하지 않아요.

\v는 세로 공백으로 간주되는 어떤 문자에 매치해요. 플랫폼의 캐리지 리턴·라인 피드(새 줄) 문자에 더해 몇 개의 다른 문자를 포함하며, 전부 아래 표에 나열돼 있어요. \V는 세로 공백으로 간주되지 않는 어떤 문자에 매치해요. 이들은 플랫폼의 네이티브 문자 집합을 쓰고, 다른 곳에서 사용 중일 수 있는 어떤 locale도 고려하지 않아요.

\R은 Unicode 규칙 아래에서 새 줄로 간주될 수 있는 무엇이든 매치해요. 다중 문자 시퀀스에 매치할 수 있어요. 브래킷 문자 클래스 안에서는 쓸 수 없어요. 대신 \v(세로 공백)를 쓰세요. 플랫폼의 네이티브 문자 집합을 쓰고, 다른 곳에서 사용 중일 수 있는 어떤 locale도 고려하지 않아요. 자세한 내용은 perlrebackslash에서 논의돼요.

\s(그리고 \d·\w)와 달리 \h\v는 활성 locale이나 소스 문자열이 UTF-8 형식인지 같은 다른 요소와 무관하게 항상 같은 문자에 매치한다는 점을 주의하세요.

\s[\h\v]와 동등하다고 생각할 수도 있어요. 이것은 실제로 Perl v5.18부터 참이지만, 그 이전에는 세로 탭("\cK")이 \s로 매치되지 않았다는 유일한 차이가 있었어요.

다음 표는 Unicode 14.0 기준으로 \s, \h, \v가 매치하는 문자의 완전한 목록이에요.

첫 열은 문자의 Unicode 코드 포인트(16진 형식), 두 번째 열은 (Unicode) 이름이에요. 세 번째 열은 그 문자가 어느 클래스(들)에 매치되는지 나타내요(\s 매치를 바꾸는 locale이 적용 중이지 않다고 가정).

0x0009        CHARACTER TABULATION   h s
0x000a              LINE FEED (LF)    vs
0x000b             LINE TABULATION    vs  [1]
0x000c              FORM FEED (FF)    vs
0x000d        CARRIAGE RETURN (CR)    vs
0x0020                       SPACE   h s
0x0085             NEXT LINE (NEL)    vs  [2]
0x00a0              NO-BREAK SPACE   h s  [2]
0x1680            OGHAM SPACE MARK   h s
0x2000                     EN QUAD   h s
0x2001                     EM QUAD   h s
0x2002                    EN SPACE   h s
0x2003                    EM SPACE   h s
0x2004          THREE-PER-EM SPACE   h s
0x2005           FOUR-PER-EM SPACE   h s
0x2006            SIX-PER-EM SPACE   h s
0x2007                FIGURE SPACE   h s
0x2008           PUNCTUATION SPACE   h s
0x2009                  THIN SPACE   h s
0x200a                  HAIR SPACE   h s
0x2028              LINE SEPARATOR    vs
0x2029         PARAGRAPH SEPARATOR    vs
0x202f       NARROW NO-BREAK SPACE   h s
0x205f   MEDIUM MATHEMATICAL SPACE   h s
0x3000           IDEOGRAPHIC SPACE   h s

[1] Perl v5.18 이전에는 \s가 세로 탭을 매치하지 않았어요. [^\S\cK]이 (난해하게) \s가 전통적으로 매치하던 것에 매치해요.

[2] NEXT LINE과 NO-BREAK SPACE는 적용 중인 규칙에 따라 \s에 매치할 수도 있고 아닐 수도 있어요. 이 섹션의 시작 부분을 보세요.

Unicode 속성 (Unicode Properties)

\pP\p{Prop}은 주어진 Unicode 속성에 맞는 문자에 매치하는 문자 클래스예요. 한 글자 속성 이름은 \pP 형태로 쓸 수 있는데, 속성 이름이 \p를 따르고, 그렇지 않으면 중괄호가 필요해요. 중괄호를 쓸 때는 중괄호 안에 속성 이름만 있는 단일 형태와 \p{name=value}처럼 생긴 복합 형태가 있는데, 후자는 문자의 속성 "name"이 특정 "value"를 가지면 매치한다는 뜻이에요. 예를 들어 숫자 매치는 / \pN/ 또는 / \p{Number}/ 또는 / \p{Number=True}/로 쓸 수 있어요. 소문자는 단축형 Ll을 가진 속성 _Lowercase_Letter_가 매치해요. 이들은 중괄호가 필요해 /\p{Ll}/ 또는 /\p{Lowercase_Letter}/ 또는 /\p{General_Category=Lowercase_Letter}/로 써요(밑줄은 선택). / \pLl/은 유효하지만 다른 것을 의미해요. 두 문자 문자열, 즉 글자(Unicode 속성 \pL) 다음에 소문자 l에 매치해요.

Unicode 속성이 매치하는 것은 결코 locale 규칙의 영향을 받지 않고, 다른 곳에서 locale 규칙이 적용 중이지 않으면 Unicode 속성의 사용은 정규식이 아직 아니라면 Unicode 규칙을 쓰도록 강제해요.

거의 모든 속성은 대소문자 구분 없는 매치에 면역이라는 점을 주의하세요. 즉 /i 정규표현식 수정자를 추가해도 그들이 매치하는 것에 변화가 없어요. 하지만 영향을 받는 두 집합이 있어요. 첫 집합은 Uppercase_Letter, Lowercase_Letter, Titlecase_Letter로, 전부 /i 매치에서 Cased_Letter에 매치해요. 두 번째 집합은 Uppercase, Lowercase, Titlecase로, 전부 /i 매치에서 Cased에 매치해요. (이 집합들의 차이는 로마 숫자 같은 일부가 대문자와 소문자 둘 다로 존재해 Cased지만, 글자로 간주되지 않아 Cased_Letter가 아니라는 거예요. 실제로는 Letter_Number예요.) 이 집합은 하위 집합 PosixUpperPosixLower도 포함하는데, 둘 다 /i에서 PosixAlpha에 매치해요.

Unicode 속성에 대한 더 자세한 내용은 "Unicode Character Properties" in perlunicode, 가능한 속성의 완전한 목록은 "Properties accessible through \p{} and \P{}" in perluniprops를 보세요. 후자는 /i 차이가 있는 모든 형태를 적어 놓아요. 자신만의 속성을 정의하는 것도 가능해요. 이것은 "User-Defined Character Properties" in perlunicode에서 논의돼요.

Unicode 속성은 (놀랍게도!) Unicode 코드 포인트에서만 정의돼요. v5.20부터 \p\P에 대해 매치할 때, Perl은 비-Unicode 코드 포인트(합법적인 Unicode 최대값 0x10FFFF보다 큰 것)를 전형적인 미할당 Unicode 코드 포인트인 것처럼 취급해요.

v5.20 이전에는 Perl이 비-Unicode 코드 포인트에서 경고를 내고 모든 매치를 실패시켰어요. 이것은 다소 놀라울 수 있었어요:

chr(0x110000) =~ \p{ASCII_Hex_Digit=True}     # Fails on Perls < v5.20.
chr(0x110000) =~ \p{ASCII_Hex_Digit=False}    # Also fails on Perls
                                              # < v5.20

이 두 매치가 보수(complement)로 생각될 수도 있지만, v5.20까지는 Unicode 코드 포인트에서만 그랬어요.

perl v5.30부터 Unicode 속성 값에 와일드카드가 허용돼요. "Wildcards in Property Values" in perlunicode를 보세요.

예시

"a"  =~  /\w/      # Match, "a" is a 'word' character.
"7"  =~  /\w/      # Match, "7" is a 'word' character as well.
"a"  =~  /\d/      # No match, "a" isn't a digit.
"7"  =~  /\d/      # Match, "7" is a digit.
" "  =~  /\s/      # Match, a space is whitespace.
"a"  =~  /\D/      # Match, "a" is a non-digit.
"7"  =~  /\D/      # No match, "7" is not a non-digit.
" "  =~  /\S/      # No match, a space is not non-whitespace.

" "  =~  /\h/      # Match, space is horizontal whitespace.
" "  =~  /\v/      # No match, space is not vertical whitespace.
"\r" =~  /\v/      # Match, a return is vertical whitespace.

"a"  =~  /\pL/     # Match, "a" is a letter.
"a"  =~  /\p{Lu}/  # No match, /\p{Lu}/ matches upper case letters.

"\x{0e0b}" =~ /\p{Thai}/  # Match, \x{0e0b} is the character
                          # 'THAI CHARACTER SO SO', and that's in
                          # Thai Unicode class.
"a"  =~  /\P{Lao}/ # Match, as "a" is not a Laotian character.

\d, \w 등이 완전한 숫자·단어가 아니라 단일 문자에 매치한다는 점을 강조할 가치가 있어요. 숫자(숫자로 구성된)를 매치하려면 \d+를, 단어를 매치하려면 \w+를 쓰세요. 다만 위에서 언급한 보안 고려사항을 인지하세요.

브래킷 문자 클래스 (Bracketed Character Classes)

Perl 정규표현식에서 쓸 수 있는 세 번째 형태의 문자 클래스는 브래킷 문자 클래스예요. 가장 단순한 형태로, 대괄호로 감싼 매치될 수 있는 문자들을 나열해요: [aeiou]처럼. 이것은 a, e, i, o, u 중 하나에 매치해요. 다른 문자 클래스처럼 정확히 한 문자가 매치돼요.* 문자 클래스에 언급된 문자들로 구성된 더 긴 문자열을 매치하려면 문자 클래스 뒤에 수량자를 붙이세요. 예를 들어 [aeiou]+는 하나 이상의 소문자 영어 모음에 매치해요.

문자 클래스에서 문자를 반복하는 것은 효과가 없어요. 집합에 한 번만 있는 것으로 간주돼요.

예시:

"e"  =~  /[aeiou]/        # Match, as "e" is listed in the class.
"p"  =~  /[aeiou]/        # No match, "p" is not listed in the class.
"ae" =~  /^[aeiou]$/      # No match, a character class only matches
                          # a single character.
"ae" =~  /^[aeiou]+$/     # Match, due to the quantifier.

* 브래킷 문자 클래스가 단일 문자만 매치한다는 것에는 두 가지 예외가 있어요. 각각 Perl의 특수 처리가 필요해요:

  • 클래스가 /i 매치 규칙 아래에서 대소문자 구분 없이 매치해야 하고, 클래스 안에서 명시적으로 언급된 문자가 Unicode 규칙 아래에서 다중 문자 시퀀스에 대소문자 구분 없이 매치한다면, 클래스도 그 시퀀스에 매치해요. 예를 들어 Unicode는 LATIN SMALL LETTER SHARP S/i 규칙 아래에서 ss 시퀀스와 매치해야 한다고 말해요. 그래서:
'ss' =~ /\A\N{LATIN SMALL LETTER SHARP S}\z/i             # Matches
'ss' =~ /\A[aeioust\N{LATIN SMALL LETTER SHARP S}]\z/i    # Matches

이것이 일어나려면 클래스가 뒤집히지 않아야("Negation" 참조) 하고, 문자가 명시적으로 지정되어야 하며, 다중 문자 범위의 일부가 아니어야 해요(심지어 그 끝점 중 하나도 아니어야 해요). ("Character Ranges"는 곧 설명돼요.) 그래서:

'ss' =~ /\A[\0-\x{ff}]\z/ui       # Doesn't match
'ss' =~ /\A[\0-\N{LATIN SMALL LETTER SHARP S}]\z/ui   # No match
'ss' =~ /\A[\xDF-\xDF]\z/ui   # Matches on ASCII platforms, since
                              # \xDF is LATIN SMALL LETTER SHARP S,
                              # and the range is just a single
                              # element

이런 유형의 범위는 어쨌든 지정하지 않는 게 좋다는 점을 주의하세요.

  • \N{...}이 아는 일부 이름은 보통의 단일 문자가 아니라 다중 문자 시퀀스를 가리켜요. 이것 중 하나가 클래스에 포함되면 전체 시퀀스가 매치돼요. 예를 들어:
"\N{TAMIL LETTER KA}\N{TAMIL VOWEL SIGN AU}"
                            =~ / ^ [\N{TAMIL SYLLABLE KAU}]  $ /x;

매치돼요. \N{TAMIL SYLLABLE KAU}는 매치 대상인 두 문자로 구성된 이름 붙은 시퀀스이기 때문이에요. 브래킷 클래스가 다중 문자를 매치할 수 있는 다른 경우처럼, 그리고 비슷한 이유로 클래스가 뒤집히면 안 되고, 이름 붙은 시퀀스가 범위에 나타나면 안 돼요(양 끝점인 경우에도). 이런 일이 일어나면, 문자 클래스가 use re 'strict'의 범위 안에 있거나 확장된 (?[...]) 클래스 안에 있으면 치명적 오류이고, 그렇지 않으면 첫 코드 포인트만 사용돼요(regexp-유형 경고가 발생).

브래킷 문자 클래스 안의 특수 문자 (Special Characters Inside a Bracketed Character Class)

정규표현식에서 메타 문자인 대부분의 문자(즉 ., *, (처럼 특별한 의미를 지니는 문자)는 특별한 의미를 잃고 문자 클래스 안에서 이스케이프 없이 쓸 수 있어요. 예를 들어 [()]는 여는 괄호나 닫는 괄호에 매치하고, 문자 클래스 안의 괄호는 그룹화·캡처하지 않아요. 패턴이 single-quotish 문맥에서 평가되지 않는 한, 브래킷 클래스가 파싱되기 전에 변수 보간이 일어난다는 점을 주의하세요:

$, = "\t| ";
$x =~ m'[$,]';        # single-quotish: matches '$' or ','
$x =~ q{[$,]};        # same
$x =~ m/[$,]/;        # double-quotish: Because we made an
                      #   assignment to $, above, this now
                      #   matches "\t", "|", or " "

문자 클래스 안에서 특별한 의미를 지닐 수 있는 문자는 \, ^, -, [, ]이고 아래에서 논의돼요. 백슬래시로 이스케이프할 수 있는데, 가끔 필요 없을 때도 있어 그 경우 백슬래시를 생략할 수 있어요.

\b 시퀀스는 브래킷 문자 클래스 안에서 특별해요. 문자 클래스 밖에서 \b는 양쪽에 두 단어 문자나 두 비-단어 문자가 없는 지점을 나타내는 어서션이지만, 브래킷 문자 클래스 안에서는 \b가 백스페이스 문자에 매치해요.

\a, \c, \e, \f, \n, \N{_NAME_}, \N{U+_hex char_}, \r, \t, \x 시퀀스도 특별하고 브래킷 문자 클래스 밖에서와 같은 의미를 가져요.

또한 백슬래시 다음에 8진 숫자 두·세 개는 8진수로 간주돼요.

[는 POSIX 문자 클래스의 시작이 아닌 한 문자 클래스 안에서 특별하지 않아요(아래 "POSIX Character Classes" 참조). 보통 이스케이프할 필요가 없어요.

]는 보통 POSIX 문자 클래스의 끝(아래 "POSIX Character Classes" 참조)이거나, 브래킷 문자 클래스의 끝을 알려요. ]를 문자 집합에 포함시키려면 일반적으로 이스케이프해야 해요.

하지만 ]가 브래킷 문자 클래스의 첫 번째(첫 문자가 caret이면 두 번째) 문자라면, 클래스의 끝을 나타내지 않아요(빈 클래스를 가질 수 없으니까) 이스케이프 없이 매치될 수 있는 문자 집합의 일부로 간주돼요.

예시:

"+"   =~ /[+?*]/     #  Match, "+" in a character class is not special.
"\cH" =~ /[\b]/      #  Match, \b inside in a character class
                     #  is equivalent to a backspace.
"]"   =~ /[][]/      #  Match, as the character class contains
                     #  both [ and ].
"[]"  =~ /[[]]/      #  Match, the pattern contains a character class
                     #  containing just [, and the character class is
                     #  followed by a ].

브래킷 문자 클래스와 /xx 패턴 수정자 (Bracketed Character Classes and the /xx pattern modifier)

보통 SPACE와 TAB 문자는 브래킷 문자 클래스 안에서 특별한 의미가 없어요. 그냥 클래스가 매치하는 문자 목록에 추가될 뿐이에요. 하지만 /xx 패턴 수정자가 적용 중이면 일반적으로 무시되고 가독성 향상을 위해 추가될 수 있어요. 단일 구조 중간에는 추가할 수 없어요:

/ [ \x{10 FFFF} ] /xx  # WRONG!

16진 상수 중간의 SPACE는 불법이에요.

리터럴 SPACE 문자를 지정하려면 백슬래시로 이스케이프할 수 있어요:

/[ a e i o u \  ]/xx

이것은 영어 모음에 더해 SPACE 문자에 매치해요.

명확성을 위해 이미 \t로 리터럴 탭을 지정하고 있었어야 하고, \t/xx의 영향을 받지 않아요.

문자 범위 (Character Ranges)

문자 범위를 매치하고 싶은 건 흔한 일이에요. 다행히 범위의 모든 문자를 나열하는 대신 하이픈(-)을 쓸 수 있어요. 브래킷 문자 클래스 안에서 하이픈으로 구분된 두 문자가 있으면, 두 문자 사이의 모든 문자가 클래스에 있는 것처럼 취급돼요. 예를 들어 [0-9]는 어떤 ASCII 숫자라도 매치하고, [a-m]은 ASCII 알파벳 전반부의 어떤 소문자라도 매치해요.

하이픈 양쪽의 두 문자가 반드시 둘 다 글자이거나 둘 다 숫자일 필요는 없다는 점을 주의하세요. 어떤 문자든 가능하지만 권장되진 않아요. ['-?]는 문자 범위를 포함하지만, 대부분의 사람은 그게 어떤 문자를 의미하는지 모를 거예요. 게다가 그런 범위는 EBCDIC 같은 다른 문자 집합을 쓰는 플랫폼에서 실행해야 한다면 이식성 문제를 일으킬 수 있어요.

문자 클래스의 하이픈이 문법적으로 범위의 일부가 될 수 없으면, 예를 들어 문자 클래스의 첫·마지막 문자이거나 범위 바로 뒤에 오면, 하이픈은 특별하지 않고 리터럴로 매치될 문자로 간주돼요. 매치될 문자 집합에 하이픈을 넣고 싶은데 그 위치가 범위의 일부로 간주될 수 있다면, 그 하이픈을 백슬래시로 이스케이프해야 해요.

예시:

[a-z]       #  Matches a character that is a lower case ASCII letter.
[a-fz]      #  Matches any letter between 'a' and 'f' (inclusive) or
            #  the letter 'z'.
[-z]        #  Matches either a hyphen ('-') or the letter 'z'.
[a-f-m]     #  Matches any letter between 'a' and 'f' (inclusive), the
            #  hyphen ('-'), or the letter 'm'.
['-?]       #  Matches any of the characters  '()*+,-./0123456789:;<=>?
            #  (But not on an EBCDIC platform).
[\N{APOSTROPHE}-\N{QUESTION MARK}]
            #  Matches any of the characters  '()*+,-./0123456789:;<=>?
            #  even on an EBCDIC platform.
[\N{U+27}-\N{U+3F}] # Same. (U+27 is "'", and U+3F is "?")

위의 마지막 두 예시처럼, 범위 끝점에 \N{...} 형태를 쓰면 비-ASCII 플랫폼으로의 이식성을 달성할 수 있어요. 이것은 지정된 범위가 Unicode 값을 사용해 해석되어야 함을 나타내므로, [\N{U+27}-\N{U+3F}]는 그 문자의 네이티브 코드 포인트 버전이 무엇이든 \N{U+27}, \N{U+28}, \N{U+29}, ..., \N{U+3D}, \N{U+3E}, \N{U+3F}에 매치하라는 뜻이에요. 이것들은 "Unicode" 범위라고 불러요. 어느 한쪽 끝이 \N{...} 형태이면 그 범위는 Unicode로 간주돼요. 다른 끝점이 비이식적으로 지정되면 "use re 'strict'" 아래에서 regexp 경고가 발생해요:

[\N{U+00}-\x09]    # Warning under re 'strict'; \x09 is non-portable
[\N{U+00}-\t]      # No warning;

위 둘 다 \N{U+00} \N{U+01}, ... \N{U+08}, \N{U+09}에 매치하지만, \x09는 실수일 수 있는 것처럼 보이므로(re 'strict' 아래에서) 경고가 발생해요.

Perl은 또한 A-Z, a-z, 0-9 범위와 그것들의 어떤 하위 범위가 영어만 쓰는 화자가 어떤 플랫폼에서 기대하는 것과 매치하도록 보장해요. 즉 [A-Z]는 26개 ASCII 대문자에, [a-z]는 26개 소문자에, [0-9]는 10개 숫자에 매치해요. [h-k] 같은 하위 범위도 대응하게 매치하는데, 이 경우 정확히 "h", "i", "j", "k" 네 글자예요. 이것은 "h"부터 "k"까지의 코드 포인트(서수값)가 연속된 정수(0x68부터 0x6B까지)인 ASCII 플랫폼에서 자연스러운 동작이에요. 하지만 비-ASCII 네이티브 문자 집합을 가진 플랫폼에서는 이를 달성하기 위해 특수 처리가 필요할 수 있어요. 예를 들어 EBCDIC 플랫폼에서 "h"의 코드 포인트는 0x88, "i"는 0x89, "j"는 0x91, "k"는 0x92예요. Perl은 [h-k]를 특수 처리해 틈의 일곱 코드 포인트 0x8A부터 0x90까지를 제외해요. 이 특수 처리는 범위가 ASCII 대문자·소문자·숫자 범위 중 하나의 하위 범위이고, AND 범위의 각 끝이 "A" 같은 리터럴 또는 이름 붙은 문자(\N{...}, \N{U+... 형태 포함)로 표현될 때만 호출돼요.

EBCDIC 예시:

[i-j]               #  Matches either "i" or "j"
[i-\N{LATIN SMALL LETTER J}]  # Same
[i-\N{U+6A}]        #  Same
[\N{U+69}-\N{U+6A}] #  Same
[\x{89}-\x{91}]     #  Matches 0x89 ("i"), 0x8A .. 0x90, 0x91 ("j")
[i-\x{91}]          #  Same
[\x{89}-j]          #  Same
[i-J]               #  Matches, 0x89 ("i") .. 0xC1 ("J"); special
                    #  handling doesn't apply because range is mixed
                    #  case

부정 (Negation)

대신 매치하고 싶지 않은 문자를 나열하는 것도 가능해요. 문자 클래스의 첫 문자로 caret(^)을 써서 할 수 있어요. 예를 들어 [^a-z]는 소문자 ASCII 문자가 아닌 어떤 문자라도 매치하는데, 따라서 백만 개가 넘는 Unicode 코드 포인트를 포함해요. 그 클래스는 "negated" 또는 "inverted"라고 불러요.

이 문법은 caret을 브래킷 문자 클래스 안에서 특수한 문자로 만들지만, 클래스의 첫 문자일 때만 그래요. caret을 매치할 문자 중 하나로 원한다면 caret을 이스케이프하거나 첫 번째로 나열하지 마세요.

뒤집힌 브래킷 문자 클래스에서 Perl은 이름 붙은 시퀀스와 특정 문자가 대소문자 구분 없는 /i 매치 아래에서 다중 문자 시퀀스에 매치해야 한다고 보통 말하는 Unicode 규칙을 무시해요. 그 규칙을 따르면 매우 혼란스러운 상황이 생길 수 있어요:

"ss" =~ /^[^\xDF]+$/ui;   # Matches!

이것은 \xDF도 아니고 /i 아래에서 \xDF가 매치하는 것도 아닌 문자 시퀀스에 매치해야 해요. "s"\xDF가 아니지만, Unicode는 "ss"/i 아래에서 \xDF가 매치하는 것이라고 말해요. 그래서 어느 쪽이 "이기나"? 문자열이 ss를 갖는다고 매치를 실패시킬까, 아니면 s 다음에 또 다른 s가 온다고 받아들일까? Perl은 후자를 선택했어요. (위 "Bracketed Character Classes"의 주석을 보세요.)

예시:

"e"  =~  /[^aeiou]/   #  No match, the 'e' is listed.
"x"  =~  /[^aeiou]/   #  Match, as 'x' isn't a lowercase vowel.
"^"  =~  /[^^]/       #  No match, matches anything that isn't a caret.
"^"  =~  /[x^]/       #  Match, caret is not special here.

백슬래시 시퀀스 (Backslash Sequences)

어떤 백슬래시 시퀀스 문자 클래스든(\N\R 제외) 브래킷 문자 클래스 안에 넣을 수 있고, 백슬래시 시퀀스가 매치하는 모든 문자를 문자 클래스 안에 넣은 것처럼 동작해요. 예를 들어 [a-f\d]는 어떤 십진 숫자 또는 'a'와 'f' 사이의 소문자(포함)에 매치해요.

브래킷 문자 클래스 안의 \N\N{_name_} 또는 \N{U+_hex char_} 형태여야 하고, 비-새 줄에 매치하는 형태가 아니어야 해요. 브래킷 문자 클래스 안의 점 .이 특별한 의미를 잃는 것과 같은 이유로, \N은 거의 무엇이든 매치해서 보통 원하는 결과가 아니기 때문이에요.

예시:

/[\p{Thai}\d]/     # Matches a character that is either a Thai
                   # character, or a digit.
/[^\p{Arabic}()]/  # Matches a character that is neither an Arabic
                   # character, nor a parenthesis.

백슬래시 시퀀스 문자 클래스는 범위의 끝점 중 하나가 될 수 없어요. 그래서 이렇게 말할 수 없어요:

/[\p{Thai}-\d]/     # Wrong!

POSIX 문자 클래스 (POSIX Character Classes)

POSIX 문자 클래스는 [:class:] 형태를 갖고, _class_는 이름, [::]는 구분자예요. POSIX 문자 클래스는 브래킷 문자 클래스 안에서만 나타나고, 문자 그룹을 나열하는 편리하고 설명적인 방법이에요.

문법에 주의하세요:

# Correct:
$string =~ /[[:alpha:]]/

# Incorrect (will warn):
$string =~ /[:alpha:]/

후자 패턴은 콜론과 글자 a, l, p, h로 구성된 문자 클래스가 될 거예요.

POSIX 문자 클래스는 더 큰 브래킷 문자 클래스의 일부가 될 수 있어요. 예를 들어:

[01[:alpha:]%]

유효하고 '0', '1', 어떤 알파벳 문자, 퍼센트 기호에 매치해요.

Perl은 다음 POSIX 문자 클래스를 인식해요:

alpha  Any alphabetical character (e.g., [A-Za-z]).
alnum  Any alphanumeric character (e.g., [A-Za-z0-9]).
ascii  Any character in the ASCII character set.
blank  Any horizontal whitespace character (e.g. space or horizontal
       tab ("\t")).
cntrl  Any control character.  See Note [2] below.
digit  Any decimal digit (e.g., [0-9]), equivalent to "\d".
graph  Any printable character, excluding a space.  See Note [3] below.
lower  Any lowercase character (e.g., [a-z]).
print  Any printable character, including a space.  See Note [4] below.
punct  Any graphical character excluding "word" characters.  Note [5].
space  Any whitespace character. "\s" including the vertical tab
       ("\cK").
upper  Any uppercase character (e.g., [A-Z]).
word   A Perl extension (e.g., [A-Za-z0-9_]), equivalent to "\w".
xdigit Any hexadecimal digit (e.g., [0-9a-fA-F]).  Note [7].

Unicode 속성처럼 대부분의 POSIX 속성은 대소문자 구분 없는(/i) 매치 적용 여부와 무관하게 같게 매치해요. 두 예외는 [:upper:][:lower:]예요. /i 아래에서 그것들은 각각 [:upper:][:lower:]의 합집합에 매치해요.

대부분의 POSIX 문자 클래스에는 Unicode 스타일 \p 속성 대응물이 두 개 있어요. (공식 Unicode 속성은 아니고, 공식 Unicode 속성에서 파생된 Perl 확장이에요.) 아래 표는 POSIX 문자 클래스와 이 대응물들의 관계를 보여줘요.

한 대응물은 표의 "ASCII-range Unicode" 열에 있고, ASCII 문자 집합의 문자에만 매치해요.

다른 대응물은 "Full-range Unicode" 열에 있고, 전체 Unicode 문자 집합에서 적절한 문자에 매치해요. 예를 들어 \p{Alpha}는 ASCII 알파벳 문자뿐 아니라 전체 Unicode 문자 집합에서 알파벳으로 간주되는 어떤 문자에도 매치해요. "backslash sequence" 열의 항목은 (짧은) 동등 표현이에요.

[[:...:]]      ASCII-range          Full-range  backslash  Note
                Unicode              Unicode     sequence
-----------------------------------------------------
  alpha      \p{PosixAlpha}       \p{XPosixAlpha}
  alnum      \p{PosixAlnum}       \p{XPosixAlnum}
  ascii      \p{ASCII}
  blank      \p{PosixBlank}       \p{XPosixBlank}  \h      [1]
                                  or \p{HorizSpace}        [1]
  cntrl      \p{PosixCntrl}       \p{XPosixCntrl}          [2]
  digit      \p{PosixDigit}       \p{XPosixDigit}  \d
  graph      \p{PosixGraph}       \p{XPosixGraph}          [3]
  lower      \p{PosixLower}       \p{XPosixLower}
  print      \p{PosixPrint}       \p{XPosixPrint}          [4]
  punct      \p{PosixPunct}       \p{XPosixPunct}          [5]
             \p{PerlSpace}        \p{XPerlSpace}   \s      [6]
  space      \p{PosixSpace}       \p{XPosixSpace}          [6]
  upper      \p{PosixUpper}       \p{XPosixUpper}
  word       \p{PosixWord}        \p{XPosixWord}   \w
  xdigit     \p{PosixXDigit}      \p{XPosixXDigit}         [7]

[1] \p{Blank}\p{HorizSpace}는 동의어예요.

[2] 제어 문자는 그 자체로 출력하지 않지만, 대신 보통 터미널을 어떻게든 제어해요: 예를 들어 새 줄과 백스페이스가 제어 문자예요. ASCII 플랫폼의 ASCII 범위에서 코드 포인트가 0부터 31(포함) 사이의 문자와 127(DEL)이 제어 문자이고, EBCDIC 플랫폼에서는 그 대응물이 제어 문자예요.

[3] graphical, 즉 보이는 어떤 문자예요. 이 클래스는 모든 영숫자 문자와 모든 구두점 문자로 구성돼요.

[4] 모든 인쇄 가능한 문자로, 모든 그래픽 문자에 더해 제어가 아닌 공백 문자들의 집합이에요.

[5] \p{PosixPunct}와 ASCII 범위의 [[:punct:]]은 모든 비-제어, 비-영숫자, 비-공백 문자에 매치해요: [-!"#$%&'()*+,./:;<=>?@[\\\]^_{|}~](locale이 적용 중이면[[:punct:]]`의 동작을 바꿀 수 있지만요).

비슷한 이름의 속성 \p{Punct}는 ASCII 범위에서 다소 다른 집합, 즉 [-!"#%&'()*,./:;?@[\\\]_{}]에 매치해요. 즉 [$+<=>^|~]` 아홉 문자가 빠져 있어요. Unicode가 POSIX가 구두점으로 간주하는 것을 Punctuation과 Symbols 두 범주로 나누기 때문이에요.

\p{XPosixPunct}와 (Unicode 규칙 아래) [[:punct:]]은 ASCII 범위에서 \p{PosixPunct}가 매치하는 것에 더해 \p{Punct}가 매치하는 것을 매치해요. 이것은 \p{Punct}에 따라 엄격히 매치하는 것과 달라요. 다시 말하면, Unicode 규칙이 적용 중이면 [[:punct:]]은 Unicode가 구두점으로 간주하는 모든 문자에 더해 Unicode가 기호로 간주하는 모든 ASCII 범위 문자에 매치해요.

[6] \p{XPerlSpace}\p{Space}는 Perl v5.18부터 동일하게 매치해요. 이전 버전에서는 비-locale 매치에서 \p{XPerlSpace}가 세로 탭 \cK를 매치하지 않았다는 점만 달랐어요. 두 ASCII 전용 범위 형태도 같아요.

[7] 태국어·데바나가리 같은 많은 문자 체계의 숫자에 매치하는 [[:digit:]]과 달리, 현재 16진 숫자 집합은 두 개뿐이고 더 추가될 가능성은 낮아요. 열 개의 숫자뿐 아니라 여섯 개의 [A-F](와 [a-f])도 대응해야 하기 때문이에요. 즉 라틴 문자만 이에 적합하고, Unicode에는 이 집합이 두 개뿐인데, 익숙한 ASCII 집합과 U+FF10(FULLWIDTH DIGIT ZERO)부터 시작하는 전각(fullwidth) 형태예요.

표에 나열된 이름 외에도 쓸 수 있는 다양한 다른 동의어가 있어요. 예를 들어 \p{XPosixAlpha}\p{Alpha}로 쓸 수 있어요. 전부 "Properties accessible through \p{} and \P{}" in perluniprops에 나열돼 있어요.

\p 대응물 둘 다 항상 Unicode 규칙이 적용 중이라고 가정해요. ASCII 플랫폼에서 이것은 128부터 255까지의 코드 포인트가 Latin-1이라고 가정한다는 뜻이고, locale이 Latin-1 또는 UTF-8임이 보장되지 않으면 locale 규칙 아래에서 그것들을 쓰는 것은 현명하지 못하다는 뜻이에요. 대조적으로 POSIX 문자 클래스는 locale 규칙 아래에서 유용해요. 실제 적용 규칙의 영향을 받는데, 다음과 같아요:

  • /a 수정자가 적용 중이면 ... 각 POSIX 클래스는 ASCII 범위 대응물과 정확히 같게 매치해요.
  • 그렇지 않으면 ...
    • 코드 포인트가 255보다 크면 ... POSIX 클래스는 Full-range 대응물과 같게 매치해요.
    • 코드 포인트가 256보다 작으면 ...
      • locale 규칙이 적용 중이면 ... POSIX 클래스는 다음을 제외하고 locale에 따라 매치해요:
        • word: locale이 무엇이든 플랫폼의 네이티브 밑줄 문자도 포함해요.
        • ascii: POSIX ascii 확장이 없는 플랫폼에서 이것은 플랫폼의 네이티브 ASCII 범위 문자만 매치해요.
        • blank: POSIX blank 확장이 없는 플랫폼에서 이것은 플랫폼의 네이티브 탭·공백 문자만 매치해요.
      • 대신 Unicode 규칙이 적용 중이면 ... POSIX 클래스는 Full-range 대응물과 같게 매치해요.
      • 그렇지 않으면 ... POSIX 클래스는 ASCII 범위 대응물과 같게 매치해요.

어떤 규칙이 적용되는지는 "Which character set modifier is in effect?" in perlre에 설명된 대로 결정돼요.

POSIX 문자 클래스의 부정 (Negation of POSIX character classes)

POSIX 문자 클래스에 대한 Perl 확장은 그것을 부정하는 능력이에요. 클래스 이름 앞에 caret(^)을 붙여 해요. 몇 가지 예를 볼게요:

        POSIX         ASCII-range     Full-range  backslash
                       Unicode         Unicode    sequence
-----------------------------------------------------
[[:^digit:]]   \P{PosixDigit}  \P{XPosixDigit}   \D
[[:^space:]]   \P{PosixSpace}  \P{XPosixSpace}
               \P{PerlSpace}   \P{XPerlSpace}    \S
[[:^word:]]    \P{PerlWord}    \P{XPosixWord}    \W

백슬래시 시퀀스는 "Which character set modifier is in effect?" in perlre에 설명된 다양한 요소에 따라 ASCII- 또는 Full-range Unicode를 의미할 수 있어요.

[= =][. .]

Perl은 POSIX 문자 클래스 [=class=][.class.]를 인식하지만 (아직?) 지원하지 않아요. 두 구조 중 어느 것을 사용하려 해도 예외가 발생해요.

예시

/[[:digit:]]/            # Matches a character that is a digit.
/[01[:lower:]]/          # Matches a character that is either a
                         # lowercase letter, or '0' or '1'.
/[[:digit:][:^xdigit:]]/ # Matches a character that can be anything
                         # except the letters 'a' to 'f' and 'A' to
                         # 'F'.  This is because the main character
                         # class is composed of two POSIX character
                         # classes that are ORed together, one that
                         # matches any digit, and the other that
                         # matches anything that isn't a hex digit.
                         # The OR adds the digits, leaving only the
                         # letters 'a' to 'f' and 'A' to 'F' excluded.

확장 브래킷 문자 클래스 (Extended Bracketed Character Classes)

(regex_sets라고도 불러요.)

이것은 더 읽기 쉽고 오류가 적은 클래스와, 교집합 같은 집합 연산을 수행하는 데 쓸 수 있는 화려한 브래킷 문자 클래스예요. 예를 하나 볼게요:

/(?[ \p{Thai} & \p{Digit} ])/

이것은 태국어 문자 체계에 있는 모든 숫자 문자에 매치해요.

이 기능은 Perl 5.18에서 실험적으로 사용 가능해졌고, 5.36에서 받아들여졌어요.

use re 'strict'가 쓰는 규칙이 이 구조에 적용돼요.

위 예시를 확장할 수 있어요:

/(?[ ( \p{Thai} + \p{Lao} ) & \p{Digit} ])/

이것은 태국어 또는 라오어 문자 체계에 있는 숫자에 매치해요.

이 예시들의 공백을 주목하세요. 이 구조는 안에서 항상 /xx 수정자가 켜져 있어요.

사용 가능한 이항 연산자는:

&    intersection
+    union
|    another name for '+', hence means union
-    subtraction (the result matches the set consisting of those
     code points matched by the first operand, excluding any that
     are also matched by the second operand)
^    symmetric difference (the union minus the intersection).  This
     is like an exclusive or, in that the result is the set of code
     points that are matched by either, but not both, of the
     operands.

단항 연산자가 하나 있어요:

!    complement

모든 이항 연산자는 좌결합이고, &가 다른 것들보다 우선순위가 높으며, 다른 것들은 모두 동일한 우선순위예요. 단항 연산자는 우결합이고 최고 우선순위예요. 따라서 이것은 논리 연산자에 대한 정상 Perl 우선순위 규칙을 따르지요. 기본 우선순위와 결합성을 덮어쓰려면 괄호를 쓰세요.

주요 제한은 모든 것이 메타문자라는 거예요. 그래서 이런 식으로 단일 문자를 참조할 수 없어요:

/(?[ a + b ])/ # Syntax error!

개별 입력 가능한 문자를 지정하는 가장 쉬운 방법은 대괄호로 감싸는 거예요:

/(?[ [a] + [b] ])/

(이것은 [ab]와 같은 거예요.) 동등하게 이렇게 말할 수도 있었어요:

/(?[[ a b ]])/

(물론 \x{...}, \N{...} 등으로 단일 문자를 지정할 수 있어요.)

이 마지막 예시는 추가 집합 연산 없이 보통 브래킷 문자 클래스를 지정하는 데 이 구조를 쓰는 걸 보여줘요. 그 안의 공백을 주목하세요. 이 구조 안에서는 /xx가 자동으로 켜지므로 허용돼요.

보통 브래킷 문자 클래스가 받아들이는 다른 모든 이스케이프도 여기서 받아들여져요.

이 구조는 use re 'strict' 아래에서 컴파일되므로, 정상 클래스에서 경고를 생성하는 인식되지 않은 이스케이프는 여기서 치명적 오류이고, 그 클래스 요소들의 다른 모든 경고와, 현재 re 'strict' 밖에서 경고하지 않는 일부 관행도 마찬가지예요. 예를 들어 이렇게 말할 수 없어요:

/(?[ [ \xF ] ])/     # Syntax error!

중괄호 없는 \x 뒤에는 두 자리 16진이 있어야 해요(두 자리를 만들려면 앞 0을 쓰세요). 이 제한은 오타로 인해 클래스가 생각한 대로 매치하지 않는 사고 빈도를 낮추기 위한 거예요.

보통 브래킷 문자 클래스가 \p{} 또는 \P{}를 포함하고 비-Unicode 코드 포인트에 대해 매치되면, 결과가 Unicode로 정의되지 않으므로 경고가 발생할 수 있어요. 이 확장 형태를 쓸 때는 그런 경고가 없어요.

보통 브래킷 문자 클래스와 이것들의 마지막 차이는, 이것들이 다중 문자 fold에 매치되게 하는 게 불가능하다는 거예요. 그래서:

/(?[ [\xDF] ])/iu

ss 문자열에 매치하지 않아요.

POSIX 클래스 이름을 이중 대괄호로 감쌀 필요가 없으므로, 다음 둘 다 동작해요:

/(?[ [:word:] - [:lower:] ])/
/(?[ [[:word:]] - [[:lower:]] ])/

포함된 어떤 POSIX 문자 클래스든(\w\D 같은 것 포함) /a(및 /aa) 수정자를 존중해요.

(?[ ])은 regex 컴파일 타임 구조라는 점을 주의하세요. 포함 정규식이 컴파일될 때 알 수 없는 것을 사용하려는 시도는 치명적 오류예요. 실무상 이것은 세 가지 제한만을 의미해요:

  1. use locale(또는 /l regex 수정자)의 범위 안에서 컴파일되면, 이 구조는 실행 타임 locale이 UTF-8일 것이라고 가정하고, 생성된 패턴은 항상 Unicode 규칙을 사용해요. 무엇이 매치되는지는 실제 런타임 locale에 의존하지 않으므로 tainting은 활성화되지 않아요. 하지만 런타임 locale이 UTF-8이 아닌 것으로 판명되면 locale 카테고리 경고가 발생해요.

  2. 사용된 어떤 사용자 정의 속성도 정규식이 컴파일될 때쯤엔 이미 정의되어 있어야 해요(단, 이 구조를 그러한 속성 대신 쓸 수 있다는 점을 주의하세요).

  3. /d 규칙으로 컴파일되었을 정규식이 이 구조를 사용하면 대신 /u를 사용해요. 따라서 이 구조는 Perl에게 그것을 포함하는 전체 정규식에 /d 규칙을 원하지 않는다고 알려줘요.

공백 건너뛰기가 이 구조의 내부에만 적용된다는 점을 주의하세요. 초기 (?[을 형성하는 문자들 사이에 공백이 있으면 안 되고, 닫는 ]) 문자들 사이에도 공백이 있으면 안 돼요.

모든 정규표현식에서처럼, 패턴은 regex 컴파일 타임에 보간되는 변수를 포함해 구축될 수 있어요. 하지만 현재는 각 하위 구성요소가 이미 컴파일된 확장 브래킷 문자 클래스여야 해요.

my $thai_or_lao = qr/(?[ \p{Thai} + \p{Lao} ])/;
...
qr/(?[ \p{Digit} & $thai_or_lao ])/;

다른 걸 보간하면 패턴이 컴파일될 수도 있고(또는 죽을 수도 있고), 컴파일되면 기대한 대로 동작하지 않을 가능성이 커요:

my $thai_or_lao = '\p{Thai} + \p{Lao}';
qr/(?[ \p{Digit} & $thai_or_lao ])/;

이것은:

qr/(?[ \p{Digit} & \p{Thai} + \p{Lao} ])/;

로 컴파일돼요. 소스 코드를 읽는 사람이 기대할 것 같은 효과가 없는데, 교집합이 라오어를 제외한 \p{Thai}에만 적용되기 때문이에요.

Perl이 파싱하는 방식 때문에 괄호와 대괄호가 주석을 포함해 균형을 이뤄야 할 수 있어요. 예시를 만나면 https://github.com/Perl/perl5/issues로 제출해 주세요. 이 매뉴얼 페이지를 위한 구체적 예시를 가질 수 있게요.

더 알아보기