本帖最后由 WHY 于 2018-1-3 20:16 编辑
今天得空,逛了逛 pstips.net,翻到 http://www.pstips.net/question/7423.html 这一贴,楼主要求用 PowerShell 正则表达式平衡组匹配 html 文档中所有 dl 嵌套标签。
PowerShell 脚本如下: | function GetBalancedConstruct { | | param([ref]$refStr); | | $match = [regex]::Matches($refStr.Value, $reg); | | $match | ForEach { | | $str = $_.Groups[0].Value; | | Write-Host ('第 ' + (++$global:n) + ' 组'); | | Write-Host $str; | | GetBalancedConstruct ([ref]$str.SubString(3)) | | } | | } | | | | $str = [IO.File]::ReadAllText('a.html', [Text.Encoding]::Default); | | $reg = '(?i)<dl>((?:(?!</?dl>)[\S\s])*|<dl>(?<Open>)|</dl>(?<-Open>))*(?(Open)(?!))</dl>'; | | | | GetBalancedConstruct ([ref]$str) | | [Console]::ReadLine() COPY |
如果感兴趣的话可以继续往下看,对脚本中正则表达式模式注释一下:<dl>(?:(?!</?dl>)[\S\s])*COPY #<dl> 后面跟着非 <dl> 或者非 </dl> 的任意字符,这样的字符重复任意次;<dl>(?<Open>)COPY #遇到 <dl> 字符,将 Open 捕获组内容压入堆栈,计数加1;</dl>(?<-Open>)COPY #遇到 </dl> 字符,将 Open 捕获组内容弹出堆栈,计数减1;(?(Open)(?!))COPY #相当于条件表达式 (?(Open)(?!Expression1)|Expression2), Expression1 和 Expression2 被省略。
#如果 <dl> 和 </dl> 个数不相等,Open 捕获组计数不为0,执行条件分支 (?!),由于 Expression1 被省略,匹配总是失败,回溯进行下一轮匹配;
#如果 <dl> 和 </dl> 个数相等,Open 捕获组计数等于0,执行条件分支 Expression2,由于 Expression2 被省略,也就是不进行任何操作,代表匹配成功。 |