DuckDB 提供了四种独立的模式匹配方法:
传统的 SQL LIKE
操作符,
较新的 SIMILAR TO
操作符(在 SQL:1999 中添加),
GLOB
操作符,
以及 POSIX 风格的 正则表达式。
LIKE
如果字符串与提供的模式匹配,LIKE
表达式返回 true
。(正如预期的那样,如果 LIKE
返回 true
,则 NOT LIKE
表达式返回 false
,反之亦然。一个等效的表达式是 NOT (string LIKE pattern)
。)
如果模式不包含百分号或下划线,那么模式仅代表字符串本身;在这种情况下,LIKE
的行为类似于等于运算符。模式中的下划线 (_
) 代表(匹配)任何单个字符;百分号 (%
) 匹配任何零个或多个字符的序列。
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
表达式相同的功能,但使用函数语法。详情请参阅文本函数文档。
搜索包含'a'后跟一个百分号再跟'c'的字符串:
SELECT 'a%c' LIKE 'a$%c' ESCAPE '$'; -- true
SELECT 'azc' LIKE 'a$%c' ESCAPE '$'; -- false
不区分大小写的 ILIKE 与 ESCAPE:
SELECT 'A%c' ILIKE 'a$%c' ESCAPE '$'; -- true
还有一些替代字符可以用作关键字,以替代LIKE
表达式。这些增强了PostgreSQL的兼容性。
LIKE风格 | PostgreSQL风格 |
---|---|
LIKE |
~~ |
不相似 |
!~~ |
ILIKE |
~~* |
不区分大小写的不匹配 |
!~~* |
SIMILAR TO
SIMILAR TO
运算符根据其模式是否匹配给定的字符串返回 true 或 false。它与 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
还有一些替代字符可以用作关键字,以代替SIMILAR TO
表达式。这些遵循POSIX语法。
SIMILAR TO -风格 |
POSIX风格 |
---|---|
类似于 |
~ |
不相似于 |
!~ |
Globbing
DuckDB 支持文件名扩展,也称为通配符匹配,用于发现文件。
DuckDB 的通配符语法使用问号 (?
) 通配符来匹配任意单个字符,使用星号 (*
) 来匹配零个或多个字符。
此外,您可以使用方括号语法 ([...]
) 来匹配方括号中包含的任何单个字符,或方括号指定的字符范围内的任何单个字符。可以在第一个方括号内使用感叹号 (!
) 来搜索不包含在方括号中的字符。
要了解更多信息,请访问 “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 Function to Find Filenames
The glob pattern matching syntax can also be used to search for filenames using the glob
table function.
It accepts one parameter: the path to search (which may include glob patterns).
在当前目录中搜索所有文件:
SELECT * FROM glob('*');
file |
---|
duckdb.exe |
test.csv |
test.json |
test.parquet |
test2.csv |
test2.parquet |
todos.json |
Globbing 语义
DuckDB的通配符实现遵循Python的glob
语义,而不是shell中使用的glob
。
一个显著的差异是**/
结构的行为:**/⟨filename⟩
不会返回顶级目录中的⟨filename⟩
文件。
例如,如果目录中存在一个README.md
文件,以下查询会找到它:
SELECT * FROM glob('README.md');
file |
---|
README.md |
然而,以下查询返回一个空结果:
SELECT * FROM glob('**/README.md');
同时,Bash、Zsh等的通配符使用相同的语法找到文件:
ls **/README.md
README.md
正则表达式
DuckDB的正则表达式支持记录在正则表达式页面上。