常用正则表达式

最近用到了正则表达式,总结下常用的正则表达式。

所有单词

'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

这是迄今我写的最复杂的正则表达式了,这个模式可以满足以下要求:

  • 匹配关键字 callfromjoin和表名;
  • 支持开头关键字排除,如排除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 正则表达式

发表评论