[REGEX] :: POSIX BRE Meta Character '' 6. ( ) ( parenthesis ) ''
IT/Regular Expression 2019. 7. 16. 10:29POSIX BRE( Basic Regular Expression )
- ^
- $
- .
- *
- \
- (
- {
- [
6. ( ) ( Parenthesis, 소괄호 )
구문 ( Syntax )
<left_paren> ::= ( <right_paren> ::= )
- 사용 예
<group_expr> <group_expr><pattern_expr><back_slash><integer> <group_expr> ::= <left_paren><pattern_expr><right_paren> <back_slash> ::= \
설명 ( Description )
- 괄호는 <group_expr>의 <pattern_expr>을 그룹화( Grouping )한다.
그룹화란, 괄호로 묶인 <pattern_expr>을 하나의 문자로 취급하는 것으로,
이를 통해 <pattern_expr>에서 메타문자들이 적용할 범위 및 순서를 지정할 수 있다.- ex) (abc)* => , abc, abcabc, abcabcabc, ...
- ex) (t|m)ake => take or make
- ex) (ab|(cd)*) => ab or , cd, cdcd, ...
- 그룹화해서 만들어지는 이 그룹들은 좌에서 우로 1번부터 차례대로 번호가 새겨진다.
그룹 시작의 기준은 <left_paren>이며, 그룹 끝의 기준은 <right_paren>이다.- ex)
ex1) pattern : '(2019)-(03)-(27)' 1번 그룹 : 2019 2번 그룹 : 03 3번 그룹 : 27 ex2) pattern : '(1(23(45)6))' 1번 그룹 : 123456 2번 그룹 : 23456 3번 그룹 : 45 ex3) pattern : '(ab(cd)e(f))g(hijk)' 1번 그룹 : abcdef 2번 그룹 : cd 3번 그룹 : f 4번 그룹 : hijk
- ex)
- 또한 매칭 과정에서, 그룹화된 <pattern_expr>이 source string과 매칭하면 각각의 그룹에 매칭된 result 값을 저장한다.
이 result 값을 'Subexpression'이라 한다.- ex)
ex1) source string : 'abcde' pattern : '(a(bcd))(e)' 1번 그룹에 string 'abcd'를 저장 2번 그룹에 string 'bcd'를 저장 3번 그룹에 string 'e'를 저장 ex2) source string : 'abcde' pattern : '(..(..).)' 1번 그룹에 string 'abcde'를 저장 2번 그룹에 string 'cd'를 저장
- ex)
- 이렇게 저장된 Subexpression값을 괄호 밖에서 <back_slash><integer> 형태로 사용할 수 있으며 이를 'Back-reference ( 역 참조 )'라 한다.
<integer>는 1 이상 9 이하의 정수이다.- ex)
ex1) source string : 'abca' pattern : '(a)bc\1' 1번 그룹에 string 'a'를 저장 subexpression 1을 back-reference matched result : 'abca' ex2) '마법 날짜'를 찾는 정규 표현식 Finding 'Magic Date' which format 'yyyy-mm-dd' 세기를 제외한 연도부분, 월 부분, 일 부분의 숫자가 모두 같은 날짜를 마법 날짜라 한다. source strings : '2010-10-10', '2009-11-26', '2004-04-04' pattern : '..(..)-\1-\1' matched result(s) : '2010-10-10', '2004-04-04' ex3) source string : 'abcdcdab' pattern : '(ab)(cd)\2\1' 1번 그룹에 string 'ab'를 저장 2번 그룹에 string 'cd'를 저장 subexpression 2를 back-reference subexpression 1을 back-reference matched result : 'abcdcdab'
- 그룹화는 10개 이상 가능하지만, 10번째 그룹부터는 역 참조할 수 없다.
- ex) (1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12)
- ex)
- 역 참조한 Subexpression에 수량자 추가도 가능하다.
- ex) (a)\1* => a, aa, aaa, ...
- 역 참조한 Subexpression또한 그룹화 및 역 참조가 가능하다.
- ex) (c)(b)(\2) => cbb
- ex) (z)(\1)\2 => zzz
- 그룹화를 하지 않고 역 참조를 하거나, 그룹화 하기 전에 역 참조를 먼저 할 경우 error 처리한다.
- ex) a\1
- ex) \1(a)
- Subexpression 관련 문서
- POSIX : POSIX 표준에서는 general한 'subexpression', 즉 말 그대로 하위 표현식 개념의 설명만 기재되어 있다.
- Oracle Regular Expressions Pocket Reference에서 발췌
- You can apply a quantifier to any arbitrary part of an expression simply by enclosing that part of the expression in parentheses.
expression의 해당 부분을 괄호로 묶는 간단한 행동으로 expression의 임의의 부분에 수량자를 적용할 수 있다.
The result is called a subexpression, and you can follow a subexpression with a quantifier to specify repetition.
그 결과를 'subexpression'으로 부르며, 이 subexpression 다음에 수량자를 기재하여 반복시킬수 있다.
- You can apply a quantifier to any arbitrary part of an expression simply by enclosing that part of the expression in parentheses.
- POSIX : POSIX 표준에서는 general한 'subexpression', 즉 말 그대로 하위 표현식 개념의 설명만 기재되어 있다.
예제 ( Examples )
SQL> SELECT REGEXP_SUBSTR( 'abc', '(a)(bc)' ) AS RESULT FROM DUAL; RESULT ------------------------------ abc SQL> SELECT REGEXP_SUBSTR( 'abab', '(ab)*' ) AS RESULT FROM DUAL; RESULT -------------------- abab SQL> SELECT REGEXP_SUBSTR( 'aabaabaac', '(a)*b\1' ) AS RESULT FROM DUAL; RESULT ------------------------------ aaba SQL> SELECT REGEXP_SUBSTR( 'aabaabaac', '(a*)b\1' ) AS RESULT FROM DUAL; RESULT ------------------------------ aabaa
SQL> SELECT REGEXP_SUBSTR( 'aa', '(a)\1' ) AS RESULT FROM DUAL; RESULT -------------------- aa SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)' ) AS RESULT FROM DUAL; RESULT -------------------- a SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)\1' ) AS RESULT FROM DUAL; RESULT -------------------- bb SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)\1\1' ) AS RESULT FROM DUAL; RESULT -------------------- ccc SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(.)\2' ) AS RESULT FROM DUAL; RESULT -------------------- abb
- 10개가 넘는 그룹화 및 역 참조
< Oracle > SQL> SELECT REGEXP_SUBSTR( '12345678901112', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)(11)(12)' ) AS RESULT FROM DUAL; RESULT ------------------------------ 12345678901112 SQL> SELECT REGEXP_SUBSTR( '12345678901', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)\1' ) AS RESULT FROM DUAL; RESULT ------------------------------ 12345678901 SQL> SELECT REGEXP_SUBSTR( '12345678900', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)\10' ) AS RESULT FROM DUAL; RESULT ------------------------------ NULL SQL> SELECT REGEXP_SUBSTR( '123456789010', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)\10' ) AS RESULT FROM DUAL; RESULT ------------------------------ 123456789010 SQL> SELECT REGEXP_SUBSTR( 'abcdefghijkli', '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\9' ) AS RESULT FROM DUAL; RESULT ------------------------------ abcdefghijkli SQL> SELECT REGEXP_SUBSTR( 'abcdefghijklj', '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\10' ) AS RESULT FROM DUAL; RESULT ------------------------------ NULL SQL> SELECT REGEXP_SUBSTR( 'abcdefghijkla0', '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\10' ) AS RESULT FROM DUAL; RESULT ------------------------------ abcdefghijkla0 < MySQL > mysql> SELECT REGEXP_SUBSTR( '12345678901112', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)(11)(12)' ) AS RESULT; +----------------+ | RESULT | +----------------+ | 12345678901112 | +----------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_SUBSTR( '12345678900', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)\\10' ) AS RESULT; +-------------+ | RESULT | +-------------+ | 12345678900 | +-------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_SUBSTR( '1234567890111212', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)(11)(12)\\12' ) AS RESULT; +------------------+ | RESULT | +------------------+ | 1234567890111212 | +------------------+ 1 row in set (0.00 sec) mysql> SELECT REGEXP_SUBSTR( 'abcdefghijkll', '(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\\12' ) AS RESULT; +---------------+ | RESULT | +---------------+ | abcdefghijkll | +---------------+ 1 row in set (0.00 sec) ※ Oracle과 MySQL 둘 다 10개 이상의 그룹화가 가능하다. - Oracle은 \10을 \1과 스트링 0으로 처리한다. - MySQL은 10번 이상의 그룹도 가능하다. < MariaDB > MariaDB [test]> SELECT REGEXP_SUBSTR( '1234567890', '(1)(2)(3)(4)(5)(6)(7)(8)(9)' ) AS RESULT; +-----------+ | RESULT | +-----------+ | 123456789 | +-----------+ 1 row in set (0.001 sec) MariaDB [test]> SELECT REGEXP_SUBSTR( '1234567899', '(1)(2)(3)(4)(5)(6)(7)(8)(9)\\9' ) AS RESULT; +------------+ | RESULT | +------------+ | 1234567899 | +------------+ 1 row in set (0.001 sec) MariaDB [test]> SELECT REGEXP_SUBSTR( '1234567890', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)' ) AS RESULT; +--------+ | RESULT | +--------+ | | +--------+ 1 row in set (0.000 sec) MariaDB [test]> SELECT REGEXP_SUBSTR( '12345678901', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)\\1' ) AS RESULT; +--------+ | RESULT | +--------+ | | +--------+ 1 row in set (0.001 sec) ※ MariaDB는 그룹이 9개를 넘을 경우 아무것도 매칭하지 않는다.
- Oracle REGEXP_SUBSTR 함수에 인자로 Subexpresison을 줄 경우
SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)', 1, 1, 'i', '1' ) AS RESULT FROM DUAL; RESULT -------------------- a SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(.)', 1, 1, 'i', '2' ) AS RESULT FROM DUAL; RESULT -------------------- b SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(.)(.)', 1, 1, 'i', '3' ) AS RESULT FROM DUAL; RESULT -------------------- b SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(.)\2(.)', 1, 1, 'i', '3' ) AS RESULT FROM DUAL; RESULT ------------------------------ c SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(.)(.)(.)', 1, 1, 'i', '4' ) AS RESULT FROM DUAL; RESULT -------------------- c SQL> SELECT REGEXP_SUBSTR( '1234567890', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)', 1, 1, 'i', '9' ) AS RESULT FROM DUAL; RESULT ------------------------------ 9 SQL> SELECT REGEXP_SUBSTR( '1234567890', '(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)', 1, 1, 'i', '10' ) AS RESULT FROM DUAL; RESULT ------------------------------ NULL
- 역 참조한 Subexpression에 수량자(quantifier)를 추가할 수도 있다.
SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)\1*', 1, 1 ) AS RESULT FROM DUAL; RESULT -------------------- a SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)\1*', 1, 2 ) AS RESULT FROM DUAL; RESULT -------------------- bb SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)\1*', 1, 3 ) AS RESULT FROM DUAL; RESULT -------------------- ccc
- 역 참조한 Subexpression을 다시 그룹화 및 역 참조할 수 있다.
SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(\1)' ) AS RESULT FROM DUAL; RESULT ------------------------------ bb SQL> SELECT REGEXP_SUBSTR( 'abbccc', '(.)(\1)\2' ) AS RESULT FROM DUAL; RESULT ------------------------------ ccc
- zero-length match group
SQL> SELECT REGEXP_SUBSTR( 'abc', '(d*)\1' ) AS RESULT FROM DUAL; RESULT -------------------- NULL SQL> SELECT REGEXP_COUNT( 'abc', '(d*)\1' ) AS RESULT FROM DUAL; RESULT ---------- 4 SQL> SELECT REGEXP_SUBSTR( 'abc', '(d*)(\1)\2' ) AS RESULT FROM DUAL; RESULT -------------------- NULL SQL> SELECT REGEXP_COUNT( 'abc', '(d*)(\1)\2' ) AS RESULT FROM DUAL; RESULT ---------- 4 ※ 그룹이 zero-length match 패턴이어도 back-reference를 한다.
- 그룹화 순서
SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b(c(d(e)))))', 1, 1, 'm', 1 ) AS RESULT FROM DUAL; RESULT ------------------------------ abcde SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b(c(d(e)))))', 1, 1, 'm', 2 ) AS RESULT FROM DUAL; RESULT ------------------------------ bcde SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b(c(d(e)))))', 1, 1, 'm', 3 ) AS RESULT FROM DUAL; RESULT ------------------------------ cde SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b(c(d(e)))))', 1, 1, 'm', 4 ) AS RESULT FROM DUAL; RESULT ------------------------------ de SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b(c(d(e)))))', 1, 1, 'm', 5 ) AS RESULT FROM DUAL; RESULT ------------------------------ e SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(((((a)b)c)d)e)', 1, 1, 'm', 1 ) AS RESULT FROM DUAL; RESULT ------------------------------ abcde SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(((((a)b)c)d)e)', 1, 1, 'm', 2 ) AS RESULT FROM DUAL; RESULT ------------------------------ abcd SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(((((a)b)c)d)e)', 1, 1, 'm', 3 ) AS RESULT FROM DUAL; RESULT ------------------------------ abc SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(((((a)b)c)d)e)', 1, 1, 'm', 4 ) AS RESULT FROM DUAL; RESULT ------------------------------ ab SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(((((a)b)c)d)e)', 1, 1, 'm', 5 ) AS RESULT FROM DUAL; RESULT ------------------------------ a SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b))((cd)e)', 1, 1, 'm', 1 ) AS RESULT FROM DUAL; RESULT ------------------------------ ab SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b))((cd)e)', 1, 1, 'm', 2 ) AS RESULT FROM DUAL; RESULT ------------------------------ b SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b))((cd)e)', 1, 1, 'm', 3 ) AS RESULT FROM DUAL; RESULT ------------------------------ cde SQL> SELECT REGEXP_SUBSTR( 'abcdeabcde', '(a(b))((cd)e)', 1, 1, 'm', 4 ) AS RESULT FROM DUAL; RESULT ------------------------------ cd SQL> SELECT REGEXP_SUBSTR( '11234567890', '(123)(4(56)(78))', 1, 1, 'm', 1 ) AS RESULT FROM DUAL; RESULT ------------------------------ 123 SQL> SELECT REGEXP_SUBSTR( '11234567890', '(123)(4(56)(78))', 1, 1, 'm', 2 ) AS RESULT FROM DUAL; RESULT ------------------------------ 45678 SQL> SELECT REGEXP_SUBSTR( '11234567890', '(123)(4(56)(78))', 1, 1, 'm', 3 ) AS RESULT FROM DUAL; RESULT ------------------------------ 56 SQL> SELECT REGEXP_SUBSTR( '11234567890', '(123)(4(56)(78))', 1, 1, 'm', 4 ) AS RESULT FROM DUAL; RESULT ------------------------------ 78 ※ 그룹화는 괄호 시작'(' 부터 순서를 매긴다.
- 그룹화를 하지 않고 역 참조
SQL> SELECT REGEXP_SUBSTR( 'abcdabcd', 'ab\1' ) AS RESULT FROM DUAL; SELECT REGEXP_SUBSTR( 'abcdabcd', 'ab\1' ) AS RESULT FROM DUAL * ERROR at line 1: ORA-12727: invalid back reference in regular expression
- 그룹화 하기 전에 역 참조
SQL> SELECT REGEXP_SUBSTR( 'abcdabcd', '\1..(ab)..' ) AS RESULT FROM DUAL; SELECT REGEXP_SUBSTR( 'abcdabcd', '\1..(ab)..' ) AS RESULT FROM DUAL * ERROR at line 1: ORA-12727: invalid back reference in regular expression SQL> SELECT REGEXP_SUBSTR( 'abcdabcd', '(ab)\2..(cd)' ) AS RESULT FROM DUAL; SELECT REGEXP_SUBSTR( 'abcdabcd', '(ab)\2..(cd)' ) AS RESULT FROM DUAL * ERROR at line 1: ORA-12727: invalid back reference in regular expression
'IT > Regular Expression' 카테고리의 다른 글
[REGEX] :: POSIX BRE Meta Character '' 8. [ ] ( bracket ) '' (0) | 2019.08.28 |
---|---|
[REGEX] :: POSIX BRE Meta Character '' 7. { } ( brace ) '' (0) | 2019.08.28 |
[REGEX] :: POSIX BRE Meta Character '' 5. \ ( back slash ) '' (0) | 2019.07.16 |
[REGEX] :: POSIX BRE Meta Character '' 4. * ( asterisk ) '' (0) | 2019.07.02 |
[REGEX] :: POSIX BRE Meta Character '' 3. . ( period ) '' (0) | 2019.07.02 |