REGEXP_EXTRACT_ALL
설명
REGEXP_EXTRACT_ALL 함수는 주어진 문자열 str에 대해 정규 표현식 일치를 수행하고, 지정된 pattern의 첫 번째 하위 패턴과 일치하는 모든 부분을 추출합니다. 이 함수는 패턴과 일치하는 부분을 나타내는 문자열을 반환하며, 패턴은 입력 문자열 str의 일부와 정확히 일치해야 합니다. 일치하는 부분이 없거나 패턴에 하위 패턴이 없으면 빈 문자열을 반환합니다.
문자 집합 일치를 처리할 때는 Utf-8 표준 문자 클래스를 사용해야 합니다. 이를 통해 함수가 다양한 언어의 문자를 올바르게 식별하고 처리할 수 있습니다.
'pattern'이 유효한 정규 표현식이 아니면 오류가 발생합니다.
기본으로 지원되는 문자 일치 클래스: https://github.com/google/re2/wiki/Syntax
Doris는 세션 변수 enable_extended_regex(기본값: false)를 통해 전후방 탐색 제로 너비 어설션과 같은 고급 정규 표현식 기능을 활성화할 수 있습니다.
세션 변수 enable_extended_regex를 true로 설정했을 때 지원되는 문자 일치 유형: https://www.boost.org/doc/libs/latest/libs/regex/doc/html/boost_regex/syntax/perl_syntax.html
구문
REGEXP_EXTRACT_ALL(<str>, <pattern>)
매개변수
| 매개변수 | 설명 |
|---|---|
<str> | String 타입의 매개변수입니다. 정규 표현식 일치를 수행할 입력 문자열을 나타냅니다. 문자열 리터럴 값이나 문자열 데이터가 있는 테이블의 컬럼 참조를 사용할 수 있습니다. |
<pattern> | 이 매개변수도 String 타입입니다. 입력 문자열 |
반환 값
인수 중 하나라도 NULL이면 NULL을 반환합니다.
이 함수는 지정된 정규 표현식의 첫 번째 하위 패턴과 일치하는 입력 문자열의 부분을 나타내는 문자열을 반환합니다. 반환 타입은 String입니다. 일치하는 부분이 없거나 패턴에 하위 패턴이 없으면 빈 문자열을 반환합니다.
기본 동작:
| 기본 설정 | 동작 |
|---|---|
.이 줄 바꿈과 일치 | 기본적으로 .은 \n(줄 바꿈)과 일치할 수 있습니다. |
| 대소문자 구분 | 일치 시 대소문자를 구분합니다. |
^/$가 전체 문자열의 경계와 일치 | ^는 문자열의 시작에만, $는 문자열의 끝에만 일치하며, 각 줄의 시작이나 끝에는 일치하지 않습니다. |
| 탐욕적 수량자 | 기본적으로 *, + 등은 가능한 한 많이 일치합니다. |
| UTF-8 | 문자열을 UTF-8로 처리합니다. |
패턴 수정자:
pattern 앞에 (?flags)를 붙여 기본 동작을 변경할 수 있습니다. 여러 수정자를 조합할 수 있습니다(예: (?im)). - 접두사는 해당 옵션을 비활성화합니다(예: (?-s)).
패턴 수정자는 기본 정규 표현식 엔진을 사용할 때만 적용됩니다. enable_extended_regex=true를 활성화한 상태에서 제로 너비 어설션(예: (?<=...), (?=...))을 사용하면 Boost.Regex 엔진이 쿼리를 처리하므로 수정자가 예상대로 동작하지 않을 수 있습니다. 두 기능을 함께 사용하지 않는 것이 좋습니다.
| 플래그 | 의미 |
|---|---|
(?i) | 대소문자를 구분하지 않고 일치 |
(?-i) | 대소문자를 구분하여 일치(기본값) |
(?s) | .이 줄 바꿈과 일치(기본적으로 활성화됨) |
(?-s) | .이 줄 바꿈과 일치하지 않음 |
(?m) | 여러 줄 모드: ^는 각 줄의 시작과, $는 각 줄의 끝과 일치 |
(?-m) | 한 줄 모드: ^/$가 전체 문자열의 경계와 일치(기본값) |
(?U) | 비탐욕적 수량자: *, + 등이 가능한 한 적게 일치 |
(?-U) | 탐욕적 수량자(기본값): *, + 등이 가능한 한 많이 일치 |
예제
'C' 앞뒤의 소문자를 찾는 기본 일치 예제입니다. 이 예제에서 패턴 ([[:lower:]]+)C([[:lower:]]+)는 하나 이상의 소문자 뒤에 'C'가 오고, 그 뒤에 다시 하나 이상의 소문자가 오는 부분과 일치합니다. 'C' 앞의 첫 번째 하위 패턴 ([[:lower:]]+)이 'b'와 일치하므로 결과는 ['b']입니다.
SELECT regexp_extract_all('AbCdE', '([[:lower:]]+)C([[:lower:]]+)');
+--------------------------------------------------------------+
| regexp_extract_all('AbCdE', '([[:lower:]]+)C([[:lower:]]+)') |
+--------------------------------------------------------------+
| ['b'] |
+--------------------------------------------------------------+
문자열에서 여러 부분이 일치하는 예제입니다. 여기서는 패턴이 문자열의 두 부분과 일치합니다. 첫 번째 일치에서는 첫 번째 하위 패턴이 'b'와 일치하고, 두 번째 일치에서는 첫 번째 하위 패턴이 'f'와 일치합니다. 따라서 결과는 ['b', 'f']입니다.
SELECT regexp_extract_all('AbCdEfCg', '([[:lower:]]+)C([[:lower:]]+)');
+-----------------------------------------------------------------+
| regexp_extract_all('AbCdEfCg', '([[:lower:]]+)C([[:lower:]]+)') |
+-----------------------------------------------------------------+
| ['b','f'] |
+-----------------------------------------------------------------+
키-값 쌍에서 키를 추출하는 예제입니다. 패턴이 문자열의 키-값 쌍과 일치합니다. 첫 번째 하위 패턴이 키를 캡처하므로 결과는 ['abc', 'def', 'ghi']입니다.
SELECT regexp_extract_all('abc=111, def=222, ghi=333','("[^"]+"|\\w+)=("[^"]+"|\\w+)');
+--------------------------------------------------------------------------------+
| regexp_extract_all('abc=111, def=222, ghi=333', '("[^"]+"|\w+)=("[^"]+"|\w+)') |
+--------------------------------------------------------------------------------+
| ['abc','def','ghi'] |
+--------------------------------------------------------------------------------+
중국어 문자를 찾는 예제입니다. 패턴 (\p{Han}+)(.+)는 첫 번째 하위 패턴 (\p{Han}+)으로 먼저 하나 이상의 중국어 문자와 일치하므로 결과는 ['这是一段中文']입니다.
select regexp_extract_all('这是一段中文 This is a passage in English 1234567', '(\\p{Han}+)(.+)');
+------------------------------------------------------------------------------------------------+
| regexp_extract_all('这是一段中文 This is a passage in English 1234567', '(\p{Han}+)(.+)') |
+------------------------------------------------------------------------------------------------+
| ['这是一段中文'] |
+------------------------------------------------------------------------------------------------+
데이터 삽입 및 REGEXP_EXTRACT_ALL 사용
CREATE TABLE test_regexp_extract_all (
id INT,
text_content VARCHAR(255),
pattern VARCHAR(255)
) PROPERTIES ("replication_num"="1");
INSERT INTO test_regexp_extract_all VALUES
(1, 'apple1, banana2, cherry3', '([a-zA-Z]+)\\d'),
(2, 'red#123, blue#456, green#789', '([a-zA-Z]+)#\\d+'),
(3, 'hello@example.com, world@test.net', '([a-zA-Z]+)@');
SELECT id, regexp_extract_all(text_content, pattern) AS extracted_data
FROM test_regexp_extract_all;
+------+----------------------+
| id | extracted_data |
+------+----------------------+
| 1 | ['apple', 'banana', 'cherry'] |
| 2 | ['red', 'blue', 'green'] |
| 3 | ['hello', 'world'] |
+------+----------------------+
일치하는 부분이 없으면 빈 문자열 반환
SELECT REGEXP_EXTRACT_ALL('ABC', '(\\d+)');
+-------------------------------------+
| REGEXP_EXTRACT_ALL('ABC', '(\\d+)') |
+-------------------------------------+
| |
+-------------------------------------+
이모지 일치
SELECT REGEXP_EXTRACT_ALL('👩💻,👨🚀', '(💻|🚀)');
+--------------------------------------------------------------+
| REGEXP_EXTRACT_ALL('👩💻,👨🚀', '(💻|🚀)') |
+--------------------------------------------------------------+
| ['💻','🚀'] |
+--------------------------------------------------------------+
'Str'이 NULL이면 NULL 반환
SELECT regexp_extract_all(NULL, '([a-z]+)');
+--------------------------------------+
| regexp_extract_all(NULL, '([a-z]+)') |
+--------------------------------------+
| NULL |
+--------------------------------------+
'pattern'이 NULL이면 NULL 반환
SELECT regexp_extract_all('Hello World', NULL);
+-----------------------------------------+
| regexp_extract_all('Hello World', NULL) |
+-----------------------------------------+
| NULL |
+-----------------------------------------+
모든 매개변수가 NULL이면 NULL 반환
SELECT regexp_extract_all(NULL,NULL);
+-------------------------------+
| regexp_extract_all(NULL,NULL) |
+-------------------------------+
| NULL |
+-------------------------------+
pattern이 유효한 정규 표현식이 아니면 오류가 발생합니다.
SELECT regexp_extract_all('hello (world) 123', '([[:alpha:]+');
ERROR 1105 (HY000): errCode = 2, detailMessage = (10.16.10.2)[INVALID_ARGUMENT]Could not compile regexp pattern: ([[:alpha:]+
Error: missing ]: [[:alpha:]+
고급 정규 표현식
SELECT REGEXP_EXTRACT_ALL('ID:AA-1,ID:BB-2,ID:CC-3', '(?<=ID:)([A-Z]{2}-\\d)');
ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[INVALID_ARGUMENT]Invalid regex pattern: (?<=ID:)([A-Z]{2}-\d). Error: invalid perl operator: (?<
SET enable_extended_regex = true;
SELECT REGEXP_EXTRACT_ALL('ID:AA-1,ID:BB-2,ID:CC-3', '(?<=ID:)([A-Z]{2}-\\d)');
+-------------------------------------------------------------------------+
| REGEXP_EXTRACT_ALL('ID:AA-1,ID:BB-2,ID:CC-3', '(?<=ID:)([A-Z]{2}-\\d)') |
+-------------------------------------------------------------------------+
| ['AA-1','BB-2','CC-3'] |
+-------------------------------------------------------------------------+
패턴 수정자
대소문자를 구분하지 않는 일치: (?i)를 사용하면 대소문자를 구분하지 않고 일치합니다.
SELECT REGEXP_EXTRACT_ALL('Hello hello HELLO', '(hello)') AS case_sensitive,
REGEXP_EXTRACT_ALL('Hello hello HELLO', '(?i)(hello)') AS case_insensitive;
+----------------+---------------------------+
| case_sensitive | case_insensitive |
+----------------+---------------------------+
| ['hello'] | ['Hello','hello','HELLO'] |
+----------------+---------------------------+
여러 줄 모드: (?m)을 사용하면 ^와 $가 각 줄의 시작과 끝에 일치합니다.
SELECT REGEXP_EXTRACT_ALL('foo\nbar\nbaz', '^([a-z]+)') AS single_line,
REGEXP_EXTRACT_ALL('foo\nbar\nbaz', '(?m)^([a-z]+)') AS multi_line;
+-------------+---------------------+
| single_line | multi_line |
+-------------+---------------------+
| ['foo'] | ['foo','bar','baz'] |
+-------------+---------------------+
탐욕적 일치와 비탐욕적 일치: (?U)를 사용하면 수량자가 가능한 한 적게 일치합니다.
SELECT REGEXP_EXTRACT_ALL('aXbXcXd', '(a.*X)') AS greedy,
REGEXP_EXTRACT_ALL('aXbXcXd', '(?U)(a.*X)') AS non_greedy;
+----------+------------+
| greedy | non_greedy |
+----------+------------+
| ['aXbXcX'] | ['aX'] |
+----------+------------+