NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
# 条件表达式 ##### **条件表达式(?(Expression)yes|no)** 它是 **(?(?=Expression)yes|no)** 的简写形式,相当于三元运算符 **(?=Expression)?yes:no** 如果“Expression”与可能出现的命名捕获组的组名相同,为避免混淆,可以采用“(?(?=Expression)yes|no)”方式显示声明“Expression”为子表达式,而不是捕获组名 表达式条件特点条件说明**(?(1)yes|no)**条件为数字分组1如果有捕获,则进行 yes 部分匹配,否则 no 部分**(?(?=a)yes|no)**条件为预搜索如果当前位置右侧是 a,则进行匹配 yes,否则匹配 no**(?(xxx)yes|no)**不与分组命名吻合如果不与任何分组命名吻合,则视为 **(?=xxx)** 相同**(?(name)yes|no)**与分组命名吻合如果与某分组命名吻合,则视为判断该分组是否进行捕获**(?(xxoo)yes)**只有一个条件表达式当只有一个条件时那么yes只能在条件成立下匹配**(?(xxoo)yes|no1|no2)**条件表达式大于2个以第一个 **|** 为准 成功匹配yes 不成功匹配no1|no2`(?(?=a)\w{2}|\w)` 当前位置右侧如果是字符“a” ,则匹配两个“\\w”,否则匹配一个“\\w” ``` <pre class="calibre10">``` $str<span class="token1">=</span><span class="token2">"a+(b*(c+d))/e+f-(g/(h-i))*j"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/\(((?<Open>\()|(?<-Open>\))|[^()]+)*(?(Open)(?!))\)/"</span><span class="token3">;</span> ``` ``` 看着难受 把他分开看容易些 ``` <pre class="calibre10">``` $pattern<span class="token1">=</span>"<span class="token1">/</span> \<span class="token3">(</span> #先匹配普通的开括号<span class="token3">(</span> <span class="token3">(</span> <span class="token3">(</span><span class="token1">?</span><span class="token1"><</span>Open<span class="token1">></span>\<span class="token3">(</span><span class="token3">)</span> #命名捕获组,遇到开括弧(则’Open’计数加<span class="token6">1</span> <span class="token1">|</span> <span class="token3">(</span><span class="token1">?</span><span class="token1"><</span><span class="token1">-</span>Open<span class="token1">></span>\<span class="token3">)</span><span class="token3">)</span> #狭义平衡组,遇到闭括弧)则’Open’计数减<span class="token6">1</span> 每匹配到一个“<span class="token3">)</span>”,就出栈最近入栈的Open捕获组,$matchs计数减<span class="token6">1</span> <span class="token1">|</span> <span class="token3">[</span><span class="token1">^</span><span class="token3">(</span><span class="token3">)</span><span class="token3">]</span><span class="token1">+</span> #非括弧的其它任意字符 <span class="token3">)</span><span class="token1">*</span> <span class="token3">(</span><span class="token1">?</span><span class="token3">(</span>Open<span class="token3">)</span><span class="token3">(</span><span class="token1">?</span><span class="token1">!</span><span class="token3">)</span><span class="token3">)</span> #判断是否还有’Open’,有则说明不配对,什么都不匹配 \<span class="token3">)</span> #匹配普通闭括号 <span class="token1">/</span>"<span class="token3">;</span> ``` ``` 后面的(?(Open)(?!))用来保证堆栈中Open捕获组计数是否为0,也就是“(”和“)”是配对出现的 5. 最后的“)”,作为匹配的结束 需要对“(?!)”进行一下说明,它属于顺序否定环视,完整的语法是“(?!Expression)”。由于这里的“Expression”不存在,表示这里不是一个位置,所以试图尝试匹配总是失败的,作用就是在Open不配对出现时,报告匹配失败 平衡组用于匹配嵌套层次结构,常用于匹配HTML标签(当HTML内容不规范,起始标签和结束标签数量不同时,匹配出正确配对的标签),在此把表达式统一以`\w`为例。 - `(?'group'\w)` 捕获的分组(`\w`匹配到的内容)命名为`group`,并压入堆栈 - `(?'-group'\w)` 捕获分组(`\w`匹配到的内容)后,弹出`group`分组栈的栈顶内容(最后压入的捕获内容),堆栈本来为空,则本分组的匹配失败 - `(?(group)yes|no)` 如果`group`栈非空匹配表达式`yes`,否则匹配表达式`no` - `(?!)` 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败 ## 平衡组分狭义平衡组与广义平衡组 ### 狭义平衡组: **(?<Close-Open>Expression)** 一般都是省略的,写作“**(?<-Open>Expression)**” 狭义平衡组指.NET中定义的(?Expression) 广义平衡组并不是固定的语法规则,而是几种语法规则的综合运用,我们平时所说的平衡组通常指的是广义平衡组。本文中如无特殊说明,平衡组这种简写指的是广义平衡组 平衡组通常是由量词,分支结构,命名捕获组,狭义平衡组,条件判断结构组成的,量词和分支结构这里不做介绍,这里只对命名捕获组,狭义平衡组和条件判断结构做下说明 > 注意:php不支持平衡组,我们可以通过递归达到同样的效果