zoukankan      html  css  js  c++  java
  • [正则表达式]PCRE反向分组引用

    在常见的文本匹配场景上,经常会需要用到一些像HTML这样的嵌套标签类型的文本匹配,经过多翻折腾,拼凑出了这样的一条语句

    (<([w]+)>((?1)|[ws])*</2>)
    

     如何理解?

    要解析上面的语句是如何运行的,先来了解一下PCRE的反向分组引用机制

    (?n)
    

     以括号为单元,紧贴左括号以?号开始,接着引用分组的序号数字,这是反向引用分组的语法

    例如,[([w]+)-(?1)]将会匹配像[9-3],[9-9]这样的结构,因为(?1)引用了第一个括号的表达式也就是([w]+),用来匹配接下来的字符

    如何得知分组的序号数字?

    例如,[([w]+(s)?)-(.*)]

    分组1将会是([w]+(s)?),

    而分组2将会是(s),

    想必你已经知道分组3将会是(.*)了。

    接下来介绍一个另外的反向分组引用机制

    '
    '
    

     以反斜杠开头,接着引用分组的序号数字,这是反向引用分组结果的语法

    和(?n)有什么不同?

    稍微更改一下刚才的语句就知道了,

    现在把[([w]+)-(?1)]更改为[([w]+)-1],再来匹配一下[9-3],[9-9],没错,现在只能匹配到[9-9]这样的结构了,因为1引用了第一个括号的表达式也就是([w]+)匹配的结果用来匹配接下来的字符,而不是直接引用执行

    现在回头看看片头给出的语句,已经不难理解了

    来解析一番:

    假设有以下一条HTML片段

    <p> i am <i> genius </i> , do you agree? </p> <p> absulutely not </p>
    

     引擎从第一个分组开始匹配(也就是整一条表达式)

    (<)

    (然后p,没有更多了,没关系,+不要求更多,继续往下)

    (>,一切都很顺利)

    (空字符,匹配了[ws],继续。。。)

    。。。

    当来到了下一个标签<i>,转折点在这里,<的出现,让原先一路往右的语句引用了整个式子,此时语句会率先执行向后引用的语句,然后等待匹配结果,当向后引用的语句再次遇到引用怎么办?显然,它的做法也会和它上一层的语句一样,直到匹配没有被继续引用,并且执行到了结尾,所有向后引用的公式会一层层的返回,这个情形类属于函数上的递归算法

     改进一下就可以支持tag属性和img这种没有结束tag的标签

    (<(div|p|table|tbody|tr|td|a)[sw='":;./#!]*>(?:(?1)|[^<]|<(?:img)s+[^>]+)*</2>)
    

     支持更多的无结束标签tag

    (<(?:(div|p|table|tbody|tr|td|a)|(img|meta|link))([sw='":;./#!-,]*)>(?(2)((?1)|[^<]|<(?3)(?4)[/]?>)*</2>))
    

     全程用到了哪些语法

    #分组捕获
    ”(?n)“
    #反向引用结果
    ”
    “
    #消除分组捕获和反向引用,运用这种语法括号中的表达式将只匹配而不会被捕获,例如(?:[a])([b])1,1捕获的分组会是([b])
    "(?:)"
    #if 流程控制,运用这种语法将会判断先前出现的分组n是否触发了匹配,如果是则启用当前括号分组的规则,例如(a)?(?(1)bb)c,只有当(a)?成功匹配了,接下来才会匹配bb
    "(reg)(?(n)trueReg|falseReg)"
    

     备注:

    JavaScript并不支持分组捕获(?n),但是支持反向引用结果

  • 相关阅读:
    Web框架&&django介绍
    bootstrap
    jQuery
    js Bom和Dom
    javascript
    css
    二分查找
    php常用函数
    基于laravel自定义测试组件
    Document
  • 原文地址:https://www.cnblogs.com/yiyide266/p/5556556.html
Copyright © 2011-2022 走看看