패턴 매칭
패턴 매칭 (Pattern Matching)
DuckDB는 네 가지 패턴 매칭 방식을 제공해요. 전통적인 SQL LIKE 연산자, 최신 SIMILAR TO 연산자 (SQL:1999에서 추가), GLOB 연산자, 그리고 POSIX 스타일의 정규식이 바로 그것이에요.
출처: 문서
본문
LIKE
LIKE 표현식은 문자열이 제공된 패턴과 일치하면 true를 반환해요. (예상대로 NOT LIKE 표현식은 LIKE가 true를 반환하면 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 %}) 문서를 참고해요.