패턴 매칭

패턴 매칭 (Pattern Matching)

DuckDB는 네 가지 패턴 매칭 방식을 제공해요. 전통적인 SQL LIKE 연산자, 최신 SIMILAR TO 연산자 (SQL:1999에서 추가), GLOB 연산자, 그리고 POSIX 스타일의 정규식이 바로 그것이에요.

출처: 문서

본문

LIKE

LIKE 표현식은 문자열이 제공된 패턴과 일치하면 true를 반환해요. (예상대로 NOT LIKE 표현식은 LIKEtrue를 반환하면 false를 반환해요. 동등한 표현식은 NOT (string LIKE pattern)이에요.)

패턴에 퍼센트 기호나 밑줄이 없으면 패턴은 문자열 그 자체만을 나타내요. 그 경우 LIKE는 등호 연산자처럼 동작해요. 패턴의 밑줄(_)은 임의의 단일 문자 하나를 나타내고(match), 퍼센트 기호(%)는 0개 이상의 문자 시퀀스를 매치해요.

LIKE 패턴 매칭은 항상 전체 문자열을 대상으로 해요. 따라서 문자열 어딘가의 시퀀스를 매치하려면 패턴이 퍼센트 기호로 시작하고 끝나야 해요.

몇 가지 예를 볼게요:

SELECT 'abc' LIKE 'abc';    -- true
SELECT 'abc' LIKE 'a%' ;    -- true
SELECT 'abc' LIKE '_b_';    -- true
SELECT 'abc' LIKE 'c';      -- false
SELECT 'abc' LIKE 'c%' ;    -- false
SELECT 'abc' LIKE '%c';     -- true
SELECT 'abc' NOT LIKE '%c'; -- false

ILIKE 키워드는 LIKE 대신 사용할 수 있는데, 활성 로케일에 따라 대소문자를 구분하지 않는 매치를 제공해요:

SELECT 'abc' ILIKE '%C'; -- true
SELECT 'abc' NOT ILIKE '%C'; -- false

와일드카드(% 또는 _)인 문자를 문자열 내에서 검색하려면, 패턴이 ESCAPE 절과 이스케이프 문자를 사용해서 그 와일드카드를 리터럴 문자로 취급해야 해요. 아래 예를 참고해요.

또한 like_escape 함수는 ESCAPE 절이 있는 LIKE 표현식과 동일한 기능을 함수 문법으로 제공해요. 자세한 내용은 [Text Functions 페이지]({% link docs/current/sql/functions/text.md %})를 참고해요.

'a' 뒤에 리터럴 퍼센트 기호, 그다음 'c'가 있는 문자열을 검색해볼게요:

SELECT 'a%c' LIKE 'a$%c' ESCAPE '$'; -- true
SELECT 'azc' LIKE 'a$%c' ESCAPE '$'; -- false

ESCAPE와 함께 쓰는 대소문자 구분 없는 ILIKE:

SELECT 'A%c' ILIKE 'a$%c' ESCAPE '$'; -- true

LIKE 표현식 대신 키워드로 사용할 수 있는 대체 문자들도 있어요. 이는 PostgreSQL 호환성을 높여줘요.

PostgreSQL 스타일 LIKE 스타일
~~ LIKE
!~~ NOT LIKE
~~* ILIKE
!~~* NOT ILIKE

SIMILAR TO

SIMILAR TO 연산자는 패턴이 주어진 문자열과 일치하는지에 따라 true 또는 false를 반환해요. [정규식]({% link docs/current/sql/functions/regular_expressions.md %})을 사용해 패턴을 해석한다는 점을 제외하면 LIKE와 유사해요. LIKE와 마찬가지로, SIMILAR TO 연산자는 패턴이 전체 문자열과 일치할 때만 성공해요. 이는 패턴이 문자열의 일부와 매치될 수 있는 일반적인 정규식 동작과는 다르답니다.

정규식은 문자열 집합(정규 집합)의 축약 정의인 문자 시퀀스예요. 문자열이 정규식에 매치된다는 것은 그 문자열이 정규식이 설명하는 정규 집합의 멤버라는 뜻이에요. LIKE와 마찬가지로, 패턴 문자가 정규식 언어의 특수 문자일 때를 제외하고는 패턴 문자는 문자열 문자와 정확히 일치해요 — 하지만 정규식은 LIKE와는 다른 특수 문자를 사용해요.

몇 가지 예를 볼게요:

SELECT 'abc' SIMILAR TO 'abc';       -- true
SELECT 'abc' SIMILAR TO 'a';         -- false
SELECT 'abc' SIMILAR TO '.*(b|d).*'; -- true
SELECT 'abc' SIMILAR TO '(b|c).*';   -- false
SELECT 'abc' NOT SIMILAR TO 'abc';   -- false

PostgreSQL에서는 ~SIMILAR TO와 동등하고 !~NOT SIMILAR TO와 동등해요. DuckDB에서는 현재 이 동등 관계가 성립하지 않아요. 자세한 내용은 [PostgreSQL compatibility 페이지]({% link docs/current/sql/dialect/postgresql_compatibility.md %})를 참고해요.

Globbing

DuckDB는 파일 이름 확장, 즉 globbing을 지원해 파일을 찾아요. DuckDB의 glob 문법은 물음표(?) 와일드카드로 임의의 단일 문자를, 별표(*)로 0개 이상의 문자를 매치해요. 또한 대괄호 문법([...])으로 대괄호 안에 포함된 임의의 단일 문자나 대괄호가 지정하는 문자 범위를 매치할 수 있어요. 첫 번째 대괄호 안에 느낌표(!)를 사용하면 대괄호 안에 포함되지 않은 문자를 검색할 수 있어요. 자세히 알아보려면 “glob (programming)” Wikipedia 페이지를 방문해요.

GLOB

GLOB 연산자는 문자열이 GLOB 패턴과 일치하면 true 또는 false를 반환해요. GLOB 연산자는 특정 패턴(예: 특정 파일 확장자)을 따르는 파일 이름을 검색할 때 가장 흔히 사용돼요.

몇 가지 예를 볼게요:

SELECT 'best.txt' GLOB '*.txt';            -- true
SELECT 'best.txt' GLOB '????.txt';         -- true
SELECT 'best.txt' GLOB '?.txt';            -- false
SELECT 'best.txt' GLOB '[abc]est.txt';     -- true
SELECT 'best.txt' GLOB '[a-z]est.txt';     -- true

대괄호 문법은 대소문자를 구분해요:

SELECT 'Best.txt' GLOB '[a-z]est.txt';     -- false
SELECT 'Best.txt' GLOB '[a-zA-Z]est.txt';  -- true

!는 대괄호 안의 모든 문자에 적용돼요:

SELECT 'Best.txt' GLOB '[!a-zA-Z]est.txt'; -- false

GLOB 연산자를 부정하려면 전체 표현식을 부정해요:

SELECT NOT 'best.txt' GLOB '*.txt';        -- false

세 개의 물결표(~~~)를 GLOB 키워드 대신 사용할 수도 있어요.

GLOB 스타일 기호 스타일
GLOB ~~~

파일 이름을 찾는 Glob 함수

glob 패턴 매칭 문법은 glob 테이블 함수로 파일 이름을 검색하는 데도 사용할 수 있어요. 이 함수는 하나의 파라미터(검색할 경로, glob 패턴 포함 가능)를 받아요.

현재 디렉토리의 모든 파일을 검색해볼게요:

SELECT * FROM glob('*');
file
duckdb.exe
test.csv
test.json
test.parquet
test2.csv
test2.parquet
todos.json

Globbing 시맨틱

DuckDB의 globbing 구현은 셸에서 쓰이는 glob이 아니라 Python의 glob의 시맨틱을 따르되, **/ 구조의 동작에 주목할 만한 차이가 있어요: **/⟨filename⟩은 최상위 디렉토리에 있는 ⟨filename⟩ 파일을 반환하지 않아요. 예를 들어 디렉토리에 README.md 파일이 있을 때, 다음 쿼리는 그 파일을 찾아요:

SELECT * FROM glob('README.md');
file
README.md

하지만 다음 쿼리는 빈 결과를 반환해요:

SELECT * FROM glob('**/README.md');

한편 Bash, Zsh 등의 globbing은 같은 문법으로 그 파일을 찾아요:

ls **/README.md
README.md

정규식 (Regular Expressions)

DuckDB의 정규식 지원은 [Regular Expressions 페이지]({% link docs/current/sql/functions/regular_expressions.md %})에 문서화되어 있어요. DuckDB는 정규식 매칭을 위한 일부 PostgreSQL 스타일 연산자를 지원해요:

PostgreSQL 스타일 동등한 표현식
~ [regexp_full_match]({% link docs/current/sql/functions/text.md %}#regexp_full_matchstring-regex)
!~ NOT [regexp_full_match]({% link docs/current/sql/functions/text.md %}#regexp_full_matchstring-regex)
~* (지원 안 함)
!~* (지원 안 함)

더 알아보기 (Learn more)

정규식 함수에 대한 자세한 내용은 [Regular Expressions]({% link docs/current/sql/functions/regular_expressions.md %}) 문서를 참고해요.