Regex在regex101可用但PowerShell中失效,求助原因
问题原因与解决办法
问题说明
测试数据示例:
^Test data This is all just test data testing 123 ABC>space "ABC" ABC>
在正则测试工具中使用(^\^|ERROR).*((|\n|\r|\w|\W)?)+(?=ABC>)能正常匹配,但PowerShell脚本中仅能匹配以ERROR开头的文件,无法匹配以^开头的文件。脚本代码如下:
$files = gci "\\server\path" $content = @() ForEach($file in $files){ $scriptname = "ABC TEST_081722" $taskname = "THIS IS A TEST!!!" $datestamp = (get-date).ToString('MMddyy') $logfilepath = "\\server\path\Logs\$($taskname)\$($file.basename).log" $log_dir = "\\server\path\Logs\$($taskname)\" $content_raw = get-content $logfilepath -raw $content_raw -match "(^\^|ERROR).*((|\n|\r|\w|\W)?)+(?=ABC>)" Write-host -f yellow $file.fullname $matches $matches.clear() start-sleep -s 2 }
核心原因
PowerShell基于.NET正则引擎,默认未启用DOTALL(单行)模式,该模式下.仅匹配除换行符外的任意字符;而你在测试工具中大概率开启了DOTALL模式,让.能跨多行匹配。
你的正则中,.*在未开启DOTALL时只能匹配^Test data这一行内容,无法覆盖后续的换行和多行文本,导致正则无法到达(?=ABC>)的断言位置,最终匹配失败。而ERROR开头的文件可能内容无换行或换行位置不影响匹配,所以能成功。
解决办法
方法1:开启DOTALL模式
在正则开头添加(?s)标记,强制.匹配所有字符(包括换行),同时简化冗余的正则部分:
$content_raw -match "(?s)(^\^|ERROR).*?(?=ABC>)"
用.*?非贪婪匹配代替原正则中冗余的((|\n|\r|\w|\W)?)+,避免过度匹配到最后一个ABC>。
方法2:用[\s\S]替代.
[\s\S]能匹配所有空白与非空白字符(即所有字符,包括换行),无需额外开启模式:
$content_raw -match "(^\^|ERROR)[\s\S]*?(?=ABC>)"
内容的提问来源于stack exchange,提问作者shadow2020
相关产品推荐
相关产品推荐

