事情是这样发生的:

最近写了很多的正则,全都是之前就会的那种,这明明就是低级的重复的劳动啊,所以要学点高级货。

事情的经过是这样的:

  • 毕竟大家正则入门靠的都是这个嘛,要学会更高级的正则的写法,那么就从平衡组(Balancing Group)开始吧,好像并不难呀,为啥总也测试不通过呢?
  • 找解决方法的时候,发现正则的限定符(quantifier)除了贪婪(greedy),懒惰(lazy)以外,还有个自私(possessive)的毛病。
  • 贪婪和懒惰我都懂,自私是个什么鬼,看起来不难的样子,先搞定它。
  • 然后发现要想正确使用“自私”限定符,需要先弄明白回溯(backtracking)是怎么回事。
  • 接着又发现要想搞清楚回溯,就要知道NFA(Nondeterministic Finite Automaton 非确定有穷状态机)的工作过程。
  • 既然研究了NFA,那DFA(Deterministic Finite Automaton 确定有穷状态机)必然也不能放过的。
  • 大功告成,等等,我开始是要干什么的来着?赶紧“回溯”。
  • 平衡组?哦,原来只有.net才支持啊,微软的黑科技之一哎。

事情就这样结束了:

  • 再次印证了“Erlang的文档中有大量的宝贝”这一真理,比如关于正则的语法,介绍的清楚而周全。同样,微软的文档良心也是大大的,相比之下,python的re模块的文档就只是个备忘录水平(当然吹毛求疵是不好的,讲道理,python的文档算得上是不错的了)。
  • 正则的手段就两种,匹配(match)和捕获(capture),虽然之前一直都隐约知道,但直到我了解了(?:之后才真正有体会。
  • 在子表达式内部可以单独设置正则选项。设置选项有两种写法,我更喜欢这一种(?imsx-imsx:exp)
  • 正则是可以进行条件判断的,条件语句有四种,子模式的引用,递归的引用,断言和伪条件DEFINE,这个DEFINE永远为,所以这个DEFINE就真的是define了,它通常就被用来定义一些子表达式。
  • 那么还有哪些表达式永远为真或者永远为假呢?(?=)(?<=)(?!)(?<!)这四个。熟悉么,它们就是断言哎,那么现在问题来了,你知道它们到底哪些为真哪些为假吗?
  • PCRE虽然没有平衡组,但是支持递归,就像递归和栈能相互转换一样,平衡组能解决的问题用递归也能做到。
  • 后向引用(Back References)和子例程(subroutine)看起来是挺像的,只不说一个是匹配了之前匹配的内容,一个匹配了之前的模式。
  • (?>表示的原子组(Atomic Grouping)在微软的文档里又叫非回溯子表达式(nonbacktracking subexpression),既然是原子的,自然就不给回溯了,很贴切。
  • 看到非回溯,自然就会想到自私限定符,这个符号的意思就是“不回溯”,所以如果原子组只需要用一次的话,就可以用自私符改写。
  • 表达式的编号可以通过数括号来确定,有时候希望子表达式里能重复编号,这时候就可以用(?|了。但它和子例程同时出现时要注意编号。
  • 微软的正则有个神奇的替换功能,跟vscode里的查找替换一模一样啊。

总结:

格物致个知:自私的一定是贪婪的。