PowerShell正则负前瞻失效:如何排除含#KEINERW的参数段
问题
需要用PowerShell的Select-String(或通用正则)匹配SQL中不含#KEINERW的@PAR开头参数所在的INSERT INTO #BASIS_VARIABLEN到EXEC sp_executesql @sql代码段,但当前正则的负前瞻未生效,仍会匹配包含#KEINERW的参数段。
原SQL片段
INSERT INTO #BASIS_VARIABLEN select ''tagid'' as ParameterTyp,IdentCode as Variable from R34_META_DELIVERY.zeit.Tag t where 1=1 '+dbo.SVF_GetAuswahlEinschraenkung('t.IdentCode',@PAR_MONAT_Stichtag)+' INSERT INTO #BASIS_VARIABLEN select ''bankid'' as ParameterTyp,BLZ as Variable from R34_ZDW.orga.Bank t where 1=1 '+dbo.SVF_GetAuswahlEinschraenkung('t.BLZ',@PAR_BLZ) INSERT INTO #BASIS_VARIABLEN select ''segmentid'' as ParameterTyp,Segment as Variable from R34_ZDW.orga.Bank t where 1=1 '+dbo.SVF_GetAuswahlEinschraenkung('t.Segment',@PAR#KEINERW_SEG_Segment) EXEC sp_executesql @sql
期望匹配结果
INSERT INTO #BASIS_VARIABLEN select ''tagid'' as ParameterTyp,IdentCode as Variable from R34_META_DELIVERY.zeit.Tag t where 1=1 '+dbo.SVF_GetAuswahlEinschraenkung('t.IdentCode',@PAR_MONAT_Stichtag)+' INSERT INTO #BASIS_VARIABLEN select ''bankid'' as ParameterTyp,BLZ as Variable from R34_ZDW.orga.Bank t where 1=1 '+dbo.SVF_GetAuswahlEinschraenkung('t.BLZ',@PAR_BLZ) EXEC sp_executesql @sql
当前PowerShell脚本(核心正则问题)
$OutputFile = "C:\Users\WRSKOI\Documents\Check_USP_VW\outfile.txt" $ErrorFile = "C:\Users\WRSKOI\Documents\Check_USP_VW\errorfile.txt" # Create or overwrite the output and error files New-Item -ItemType File -Path $OutputFile -Force | Out-Null New-Item -ItemType File -Path $ErrorFile -Force | Out-Null # 问题正则:负前瞻未生效 $RegexPattern = "(?s)INSERT\sINTO\s#BASIS_VARIABLEN.*?@PAR_(?!#KEINERW)(?:TAG|MONAT|DATUM|DATUMVONBIS|BLZ|SEG|BER|GES|MAR|SPR|KSG|KST|REF|TEXT|KTO|TEXTAREA)[\w-]*.*?EXEC\s+sp_executesql\s+@sql" # Get all .txt files in the specified directory (recursively) Get-ChildItem -Path "C:\Users\WRSKOI\Documents\Check_USP_VW\TestUSP" -Filter "*.txt" -Recurse | ForEach-Object { try { $File = $_.FullName # Read the entire file as a single string for multiline regex matching $FileContent = Get-Content -Path $File -Raw # Use Select-String to match multiline pattern in the content $Matches = [regex]::Matches($FileContent, $RegexPattern) # If any matches are found, write them to the output file if ($Matches) { foreach ($Match in $Matches) { $LineNumber = ($FileContent.Substring(0, $Match.Index).Split("`n").Count) # Calculate line number $Output = "File: $File, Line: $LineNumber, Match: $($Match.Value)" Add-Content -Path $OutputFile -Value $Output } } } catch { # Log any exceptions to the error file $_.Exception.Message | Add-Content -Path $ErrorFile } }
解决方案
问题根源
- 原正则的负前瞻
(?!#KEINERW)绑定的是@PAR_,但目标违规参数是@PAR#KEINERW(无下划线),导致负前瞻完全没命中目标位置。 .*?的非贪婪匹配无法阻止包含违规参数的内容被纳入匹配范围。
修正后的正则
(?s)(INSERT\sINTO\s#BASIS_VARIABLEN(?:(?!@PAR#KEINERW).)*?)EXEC\s+sp_executesql\s+@sql
正则解释
(?s):单行模式,让.匹配换行符,支持跨多行匹配INSERT\sINTO\s#BASIS_VARIABLEN:匹配代码段起始标记(?:(?!@PAR#KEINERW).)*?:核心排除逻辑——非捕获组,逐个字符检查,只要当前位置后不是@PAR#KEINERW就匹配该字符,直到遇到结束标记(非贪婪匹配避免过度匹配)EXEC\s+sp_executesql\s+@sql:匹配代码段结束标记
脚本替换说明
将脚本中的$RegexPattern替换为上述修正后的正则即可,无需修改其他逻辑。该正则符合PCRE标准,可直接复用至Python、Java、C#等其他语言。
内容的提问来源于stack exchange,提问作者StingerWolf
相关产品推荐
相关产品推荐

