SomeeLab.tools

正则表达式测试

把正则表达式放到自己的文本上试一试,高亮每一处匹配,并给出捕获组和替换结果。运行在单独的线程里,就算表达式失控,页面也不会卡住。

四个标志各管什么

不勾 g 就只找第一处匹配。要数个数或者全部替换,必须打开。

i 忽略大小写。m^$ 按行生效,而不是只认整段字符串的头尾,从多行日志里挑行首时就靠它。

s. 也能匹配换行。默认情况下点号不跨行,所以要整块抓住横跨好几行的内容,得开这个标志。

值得记住的零件

  • \d 数字,\w 字母数字和下划线,\s 空白。写成大写(\D \W \S)意思相反。
  • + 一个或多个,* 可以没有,? 可有可无,{2,4} 两到四次。
  • ^ 开头,$ 结尾,\b 单词边界。
  • (...) 是捕获组,会留在结果里;(?:...) 只分组不捕获。
  • 写成 (?<name>...) 就能用名字而不是编号取值。

贪婪与懒惰

.* 会一路吃到底再往回退。对 <b>一</b><b>二</b><b>.*</b>,整段会被当成一处匹配吞掉。

加个问号写成 <b>.*?</b>,它会在最早能停的地方停下,于是分成两处。要取标签或引号里面的东西,一般都该用这种写法。

为什么放在单独的线程里跑

量词一旦嵌套,正则就可能失控。给 (a+)+b 喂三十来个 a 就是这种情况:引擎要把这些 a 的每种拆法都试一遍,工作量成数量级地涨。输入明明很短,却要跑上好几分钟。

这个工具把正则放在与页面分开的线程上执行,超过一秒就把那条线程整个结束掉。因为这一切发生在一次调用内部,中途没有办法叫停。所以就算填进失控的表达式,页面照样能动。

同样的事发生在服务器上,就会有一个请求把 CPU 占住。如果你的代码会把用户输入交给正则,尤其要检查有没有嵌套的量词。

各种语言的写法并不一样

这里跑的是 JavaScript 的正则。后行断言((?<=...))在当前浏览器可用,但递归、原子组这些 PCRE 独有的功能并不存在。

Python 的命名组写作 (?P<name>...),Java 则要在字符串里再转义一层反斜杠。把这里调好的表达式搬过去时,记得换成那门语言的写法。