模式匹配
Goose 提供四种独立的模式匹配方式:
传统 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
结合 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。它与 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
In PostgreSQL,
~is equivalent toSIMILAR TOand!~is equivalent toNOT SIMILAR TO. In Goose, these equivalences do not hold currently, see the PostgreSQL compatibility page.在 PostgreSQL 中,
~等价于SIMILAR TO,!~等价于NOT SIMILAR TO。 但在 Goose 中目前并非如此, 详见 PostgreSQL 兼容性页面。
Globbing
Goose 支持文件名展开(也称 globbing)用于发现文件。
Goose 的 glob 语法中,问号(?)通配任意单个字符,星号(*)通配零个或多个字符。
此外,你还可以使用方括号语法([...])匹配方括号内任意单个字符,或方括号指定范围内的任意单个字符。可在首个方括号内使用感叹号(!)来匹配不在该集合中的字符。
更多信息可参阅 “glob (programming)” 维基百科页面。
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 |
|---|
| goose.exe |
| test.csv |
| test.json |
| test.parquet |
| test2.csv |
| test2.parquet |
| todos.json |
Globbing 语义
Goose 的 globbing 实现遵循 Python glob 的语义,而不是 shell 中 glob 的语义。
一个显著差异是 **/ 结构的行为:**/⟨filename⟩ 不会返回位于顶层目录中的 ⟨filename⟩ 文件。
例如,目录中存在 README.mdx 文件时,以下查询可以找到它:
SELECT * FROM glob('README.mdx');
| file |
|---|
| README.mdx |
但下面的查询会返回空结果:
SELECT * FROM glob('**/README.mdx');
而 Bash、Zsh 等 shell 的 globbing 在相同语法下可以找到该文件:
ls **/README.mdx
README.mdx
Regular Expressions
Goose 对正则表达式的支持记录在正则表达式页面。 Goose 支持一些 PostgreSQL 风格的正则匹配运算符:
| PostgreSQL 风格 | 等价表达式 |
|---|---|
~ | regexp_full_match |
!~ | NOT regexp_full_match |
~* | (not supported) |
!~* | (not supported) |