玩转一下正则表达式
看了一篇用正则把自己玩死的博客,代码是这个样子的,结果是把 cpu 跑死,或者跑不出来结果。
public static void main(String[] args) { String badRegex = "^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\\\/])+$"; String bugUrl = "http://www.fapiao.com/dddp-web/pdf/download?request=6e7JGxxxxx4ILd-kExxxxxxxqJ4-CHLmqVnenXC692m74H38sdfdsazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf"; if (bugUrl.matches(badRegex)) { System.out.println("match!!"); } else { System.out.println("no match!!"); } }
正则:^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$
字串:http://www.fapiao.com/dddp-web/pdf/download?request=6e7JGxxxxx4ILd-kExxxxxxxqJ4-CHLmqVnenXC692m74H38sdfdsazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf
拷贝到 Online regex tester and debugger: PHP, PCRE, Python, Golang and JavaScript 的 regex101 试一下,也能看到报告了灾难性回溯 Catastrophic backtracking
错误。
点击左边的 Debugger,会有 动画显示匹配过程,是一个很好地可视化过程。
最简单的修复,是调整一下 正则,让匹配能成功进行,但是这个只是治标,还得考虑治本:
- 识别清晰正则表达式的场景(本例就不是正则表达式的正确使用场景,而应该使用类似于URLParser的解析器。
- Java 正则匹配,可以作出某种限定,避免灾难性回溯。
想起若干年前,做靓号规则的时候,电信的 BOSS 系统也是用正则表达式来匹配一个手机号码,是否符合 AABB,或者 AAAA 等模式的,正则表达式写起来也是相当不好看,真是王婆婆的裹脚又臭又长,所以轮到我来玩了,我就直接实现了 ABC 表达式,直接配置 AABB 或者 AAAA 等形式的表达式,就可以匹配是否是某种级别的靓号了,不亦乐乎。
在 Removing the MySQL root password 上看到一个正则 temporary password(.*): \K(\S+)
,不理解其中的 \K
的含义,查询文档,了解了是重置前面所有的捕获,还有这种骚骚的用法
\K can be used to reset the match start since PHP 5.2.4. For example, the pattern foo\Kbar matches "foobar", but reports that it has matched "bar". The use of \K does not interfere with the setting of captured substrings. For example, when the pattern (foo)\Kbar matches "foobar", the first substring is still set to "foo".
参考
------------------------------------
grep 提取多个值 ggrep -oP "appId.:.\K([\w_]+)|deviceId.:.\K([\w_]+)" 1.log paste -d ' ' - -
regex101
$ grep -oP "appId.:.\K([\w_]+)|deviceId.:.\K([\w_]+)" 1.log | paste -d ' ' - - APP_79D5EC7B7C55465F8FB8114C87517CF6 DEV_C77897738BF243B1AA1E8E316850F410 APP_79D5EC7B7C55465F8FB8114C87517CF6 DEV_C77897738BF243B1AA1E8E316850F410 APP_79D5EC7B7C55465F8FB8114C87517CF6 DEV_C77897738BF243B1AA1E8E316850F410 DEV_37A4DD248CDC4DB7ADE0D3626CAB24CA APP_1698D243C3D04C46B1D488EBAE2F8348
jq 提取 grep -oP "\[\K({.*})(?=\])" 1.log | jq -c '. | {appId: .appId, deviceId: .deviceId}'
regex101
$ grep -oP "(?<=\[)({.*})(?=\])" 1.log | jq -c '. | {appId: .appId, deviceId: .deviceId}' {"appId":"APP_79D5EC7B7C55465F8FB8114C87517CF6","deviceId":"DEV_C77897738BF243B1AA1E8E316850F410"} {"appId":"APP_79D5EC7B7C55465F8FB8114C87517CF6","deviceId":"DEV_C77897738BF243B1AA1E8E316850F410"} {"appId":"APP_79D5EC7B7C55465F8FB8114C87517CF6","deviceId":"DEV_C77897738BF243B1AA1E8E316850F410"} {"appId":"APP_1698D243C3D04C46B1D488EBAE2F8348","deviceId":"DEV_37A4DD248CDC4DB7ADE0D3626CAB24CA"}
- demo 1.log
- How to use grep to extract multiple groups
brew install grep
How to install and use GNU Grep in OSX
---------------------------------------------------------
从 正则表达式详细介绍 里面看到在线工具 regexr.com 也不错,可以作为一个备份工具
--------------------------------------
普通人的正则表示式教程 一本免费的英文教程,向初学者介绍正则表达式,实例较多。
每一个正则,都有在线的解析高烈显示以及结构化图,例如:
UUID
[\da-f]{8}-([\da-f]{4}-){3}[\da-f]{12}/i
RegExr Visual
一些资源
- awesome-regex A curated collection of awesome Regex libraries, tools, frameworks and software
- regex tag on StackOverflow
- StackOverflow RegEx FAQ
- r/regex
- RexEgg
- Regular-Expressions.info
- Regex Crossword
- Regex Golf
-------------------------------------------------
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 技术走查提纲分析
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论