使用正则捕获组匹配嵌套begin-end代码块失败求助
匹配嵌套Pascal风格begin-end代码块的PowerShell正则修正
问题说明
需要用PowerShell正则表达式匹配包含嵌套结构的Pascal风格begin-end代码块(如下示例),同时排除后续独立的begin stuff2 end块,但当前实现无法正常工作。
期望匹配的嵌套代码块:
begin begin stuff1 end end
用户原代码
$ErrorActionPreference = 'Stop'; # Want to match balanced begin-end block include nested begin-end: # begin begin stuff1 end end $t1 = "" $t1 += " begin" $t1 += " begin" $ti += " stuff1" $t1 += " end" $t1 += " end" $t1 += "" $t1 += " begin" $ti += " stuff2" $t1 += " end" write-host "LINE: $t1" $rxop = [Text.RegularExpressions.RegexOptions]::IgnorePatternWhitespace -bor [Text.RegularExpressions.RegexOptions]::IgnoreCase $rx = [Regex]::new( "^(\n \bbegin\b \n (?: \n (?<openp> \bbegin\b )\n | \n (?<-openp> \bend\b )\n |\n [^\t]+ \n )+ \n\n (?<openp>)(?!))\n\n \bend\b)\n ", $rxop ) $match = $rx.Match($t1) if ($match.Success) { $name = $match.Groups[1].Value write-host "matched: $name" } else { write-host "no-match" }
问题分析与修正
原正则存在语法错误、锚点限制、过度匹配等问题,以下是修正后的代码:
$ErrorActionPreference = 'Stop'; # 构造测试文本(修正原代码中$ti的笔误,改用Here-String保证格式准确) $t1 = @" begin begin stuff1 end end begin stuff2 end "@ Write-Host "测试文本:`n$t1`n" # 正则选项:忽略空白、不区分大小写、单行模式(让.匹配换行) $rxop = [Text.RegularExpressions.RegexOptions]::IgnorePatternWhitespace ` -bor [Text.RegularExpressions.RegexOptions]::IgnoreCase ` -bor [Text.RegularExpressions.RegexOptions]::Singleline # 平衡组正则:匹配嵌套的begin-end块 $rx = [Regex]::new(@" \bbegin\b (?: (?<open>\bbegin\b) # 遇到begin,增加计数器 | (?<-open>\bend\b) # 遇到end,减少计数器 | (?!\bbegin\b|\bend\b). # 匹配非begin/end的任意字符 )+ (?(open)(?!)) # 确保计数器为0(所有begin都匹配了对应的end) \bend\b "@, $rxop) # 只匹配第一个符合条件的嵌套块 $match = $rx.Match($t1) if ($match.Success) { Write-Host "匹配到的嵌套块:`n$($match.Value)" } else { Write-Host "未匹配到" }
修正点说明
- 修复原代码中
$ti的笔误,用Here-String构造测试文本,保证格式清晰准确 - 增加
Singleline选项,让.可以匹配换行符,正确处理多行内容 - 修正平衡组语法,使用PowerShell支持的
(?<open>和(?<-open>格式 - 通过
(?(open)(?!))确保所有begin都有对应的end,实现真正的嵌套匹配 - 去掉不必要的锚点限制,适配开头带空格的代码块
- 用
(?!\bbegin\b|\bend\b).精准匹配非begin/end内容,避免过度匹配
内容的提问来源于stack exchange,提问作者Bimo
相关产品推荐
相关产品推荐

