最近用到了正则表达式,总结下常用的正则表达式。
所有单词
'pear orange apple abc123 oracle'.match(/\b[a-z]+\b/gi);
//pear orange apple oracle
以指定字符串开头的单词
一个条件
以 app 开头的单词
'pear orange apple abc123 oracle'.match(/\bapp[a-z]*\b/gi);
//apple
也可以写成这样:
'pear orange apple abc123 oracle'.match(/(\bapp)(?<=\1)[a-z]*\b/gi);
//apple
总体来讲,这个模式不如上一个模式直接,好在可以通过这个模式来了解断言和引用两种语法:
这里使用了后行断言语法 (?<=y)x
,仅当 x 前是 y 时匹配 x:(?<=\1)
中的\1
引用的是模式 (\bapp)
所匹配的文本(即开头是 app 三个字母,\b
是词边界),(?<=\1)
表达的意思是只在开头是 app 时匹配后续的字母。 (\bapp)
和 (?<=\1)[a-z]*
合到一起就是开头的 app 加上后续的字母 le,得到 apple 。
多个条件
以 app 或 ora 开头的单词
'pear orange apple abc123 oracle'.match(/\b(app|ora)[a-z]*\b/gi);
//orange apple oracle
这里通过 (x|y)
语法实现多个条件任选
以指定字符串结尾的单词
以 le
结尾的单词
'pear orange apple abc123 oracle'.match(/\b[a-z]*\Ble\b/gi);
//apple oracle
不以指定字符串开头的单词
比较拗口,也可以说以非指定字符串开头的单词。这里以非 app
开头的单词为例
'pear orange apple oracle'.match(/\b(?!app)[a-z]*/gi);
//pear orange oracle
不以指定字符串结尾的单词
非 le
结尾的单词
'pear orange apple abc123 oracle'.match(/[a-z]*(?<!le)\b/gi);
//pear orange
以下为本次任务用到的模式:
匹配 sql 语句中的注释
匹配 sql 语句中的注释部分,sql 注释有两种形式:--
和/**/
/(\/\*(.|\r\n)\*\/|\-{2,}[^(\r\n)].*(\r\n)*)/gi
其中\/\*(.|\r\n)\*\/
匹配/**/
形式的注释,之所以将它方前面,是因为这里使用了任选模式 (x|y)
,在找到匹配项之前,它会从左到右依次匹配任选模式,一旦匹配到左边的就不会继续匹配右边的任选模式了。现实中/**/
注释中可能会存在--
形式的字符,这就要求匹配/**/
形式注释的模式优先(靠左),否则将会出现匹配不到的情况。
匹配 sql 语句中用到的表和函数
/\b((call|join)[\s\r\n\t]+(?!(\"?\w+\"?\.?\"?)?(t[e]?mp_|ds_|unnest|query_str|json_|splittable|\())\1+\"?\w+\"?\.?\"?\w*)|\b(((from)[\s\r\n\t\b\(]+)(?!(\"?\w+\"?\.?\"?)?(t[e]?mp_|ds_|unnest|query_str|json_|splittable|(\bselect)))\1+\"?\w+\"?\.?\"?\w*)|[\s\r\n\t\b]*crm_\w+\b/gi
这是迄今我写的最复杂的正则表达式了,这个模式可以满足以下要求:
- 匹配关键字
call
、from
或join
和表名; - 支持开头关键字排除,如排除
tmp_
开头的; - 支持开头指定关键字,如匹配所有
crm_
开头的; - 支持以下 sql 写法:
select a.c1,d.c4
from (((t1 a left outer join t2 b on (a.c1 = b.c1))
left outer join t3 c on ( b.c2 = c.c2))
left outer join t4 d on ( c.c3 = d.c3))
参考:MDN 正则表达式