regex - 如何使用正则表达式突出显示 SQL 关键字?
问题描述
我想在语法荧光笔中突出显示字符串中出现的 SQL 关键字。以下是我想要的规则:
- 匹配关键字 SELECT 和 FROM(将添加其他关键字,但我们将从这里开始)。必须全大写
- 必须包含在字符串中——以
'
或开头"
- 该字符串中的第一个单词(忽略它前面的空格)应该是关键字之一。
这当然并不全面(可以忽略字符串中的转义),但我想从这里开始。
这里有一些例子:
- SELECT * FROM main -- 不匹配(不在字符串中)
- " SELECT name FROM main" -- 将匹配
- "
SELECT name FROM main" -- 将匹配 - """这是一条SQL语句:
SELECT * FROM main""" -- 不,字符串不以关键字开头 (SELECT...)。
我认为在单个正则表达式中执行此操作的唯一方法是向后看负数……但它不会是固定宽度,因为我们不知道字符串何时开始。就像是:
但这当然行不通:
这样的事情可以在单个正则表达式中完成吗?
解决方案
一个合适的正则表达式可能会变得相当复杂,尤其是随着规则的进一步发展。正如其他人所指出的,可能值得考虑使用解析器。也就是说,这是一个可能的正则表达式,试图涵盖到目前为止提到的规则:
(["'])\s*(SELECT)(?:\s+.*)?\s+(FROM)(?:\s+.*)?\1(?:[^\w]|$)
在线演示
解释
从上面的可视化中可以看出,正则表达式在开头查找双引号或单引号(保存在捕获组 #1 中),然后在末尾通过\1
. 和关键字在捕获组#2 和#3 中捕获SELECT
。(语法确保没有更多组用于其他选择,因为在选择开始时将其排除为捕获组。)还有一些进一步的可选细节,例如限制 and 之间允许的内容以及不计算最后的引号如果它紧跟一个单词字符。FROM
(?:x|y)
?:
SELECT
FROM
结果
SELECT * FROM tbl -- no match - not in a string
"SELECT * FROM tbl" -- matches - in a double-quoted string
'SELECT * FROM tbl;' -- matches - in a single-quoted string
'SELECT * FROM it's -- no match - letter after end quote
"SELECT * FROM tbl' -- no match - quotation marks don't match
'SELECT * FROM tbl" -- no match - quotation marks don't match
"select * from tbl" -- no match - keywords not upper case
'Select * From tbl' -- no match - still not all upper case
"SELECT col1 FROM" -- matches - even though no table name
' SELECT col1 FROM ' -- matches - as above with more whitespace
'SELECT col1, col2 FROM' -- matches - with multiple columns
可能的改进?
可能还需要从“任何字符”部分中排除引号。这可以使用此处描述的技术通过替换 with 的两个实例以.*
增加复杂性为代价来完成(?:(?!\1).)*
:
(["'])\s*(SELECT)(?:\s+(?:(?!\1).)*)?\s+(FROM)(?:\s+(?:(?!\1).)*)?\1(?:[^\w]|$)
请参阅此 Regex101 演示。
推荐阅读
- testing - Geb Groovy 测试:如何在不关闭浏览器的情况下关闭当前选项卡?
- python - 从 GUI 小部件更新 QThread
- python - 使用 CUDA 支持运行时,Tensorflow 崩溃
- yubico - 具有 HTTPS 访问权限的 Yubico YubiHSM2 连接器
- sql - JDBC 模板中的 DATEADD
- groovy - 我想将一个字符串数组传递给 main 但在 groovy 中保留空格
- installshield - 如何在确认卸载提示中添加产品名称?
- docker - overlay2 目录中带有附录“-init”的目录的含义
- sql - ora-01722 在两个视图的减号运算符上使用 count(1) 的无效数字
- talend - tjavaFlex 组件架构