如何用正则直接匹配验证逗号分隔的多模式字符串
正则表达式匹配逗号分隔的多模式字符串问题
需求说明
我有一个逗号分隔的多模式字符串,需要完成两项验证:
- 每种模式可匹配零个或多个逗号分隔的子串;
- 不存在不符合任何模式的子串。
注意:子串仅以逗号分隔,逗号后可能存在尾随空格,可先通过替换移除
目前已通过将字符串按逗号拆分为数组的方式实现功能,现在希望无需拆分数组,直接用正则对原字符串匹配,提取符合各类模式的子串到数组,同时需要知道如何快速识别存在不符合模式的子串。
需要匹配的模式
- (a) 单个数字(最多4位):示例
1、2、300 - (b) 数字范围(两端均最多4位):示例
1-5、23-45 - (c) 带
r的范围(两端均最多4位):示例r1-r50、r45-r4 - (d) 含
z的范围:示例1-z、z-100 - (e) 包含
:odd或:even的字符串:示例12-34:odd、34-4:even
现有实现的正则与代码
现有正则表达式
(a) ^\d{0,5}*$ (b) ^\d{0,5}-\d{0,5}*$ (c) (?:z) (d) (?:r) (e) (?:odd|even)
PowerShell代码片段
$reg1 = '^\d{0,5}*$' $reg2 = '^\d{0,5}-\d{0,5}*$' $reg3 = '(?:z)' $reg4 = '(?:r)' $reg5 = '(?:odd|even)'
应用逻辑
$phase1 = $rangearray | Select-String $reg1 -AllMatches | %{$_.Line} | sort # single numbers only if($phase1.count -gt 0) { $Allpages[0].Single = $true; $Allpages[1].Single = @($phase1); } $phase1 = $rangearray | Select-String $reg2 -AllMatches | %{$_.Line} # number ranges if($phase1.count -gt 0) { $Allpages[0].Ranged = $true; $Allpages[1].Ranged = {$phase1}.Invoke(); } $phase1 = $rangearray | Select-String $reg3 -AllMatches | %{$_.Line} # max range option z if($phase1.count -gt 0) { $Allpages[0].Z = $true; $Allpages[1].Z = @($phase1); } $phase1 = $rangearray | Select-String $reg5 -AllMatches | %{$_.Line} # odds and evens if($phase1.count -gt 0) { $Allpages[0].OddEven = $true; $Allpages[1].OddEven = @($phase1); }
测试字符串示例
$range = '1-2,12-14,27-25,300-270,r10-r15,450-470:odd' $range = '4, 2, 5, 14-12,16-18,20-19,r3-r1,285-290,r7-r4,388-z'
解决方案
1. 提取各类子串的正则表达式
先处理原字符串的空格问题:
$range = $range -replace ',\s+', ',' # 移除逗号后的尾随空格
针对每种模式,可直接从原字符串匹配提取的正则:
- 匹配(a)单个数字(最多4位):
\b\d{1,4}\b
说明:\b是单词边界,避免误匹配范围中的数字片段 - 匹配(b)数字范围(两端最多4位):
\b\d{1,4}-\d{1,4}\b - 匹配(c)带r的范围:
\br\d{1,4}-r\d{1,4}\b - 匹配(d)含z的范围:
\b(?:\d{1,4}-z|z-\d{1,4})\b - 匹配(e)含
:odd/:even的字符串:\b(?:\d{1,4}-\d{1,4}):(?:odd|even)\b
如果要一次性提取所有符合任意模式的子串,可合并所有模式为一个正则:
$allPatterns = '\b(?:\d{1,4}|\d{1,4}-\d{1,4}|r\d{1,4}-r\d{1,4}|\d{1,4}-z|z-\d{1,4}|\d{1,4}-\d{1,4}:(?:odd|even))\b' $matches = [regex]::Matches($range, $allPatterns) $extractedSubstrings = $matches.Value | Select-Object -Unique
2. 快速识别不符合模式的子串
方法1:验证整个字符串合法性
编写匹配完整合法字符串的正则,要求所有子串均符合模式:
$fullValidationPattern = '^(?:\s*(?:\d{1,4}|\d{1,4}-\d{1,4}|r\d{1,4}-r\d{1,4}|\d{1,4}-z|z-\d{1,4}|\d{1,4}-\d{1,4}:(?:odd|even))\s*(?:,|$))+$' if ($range -match $fullValidationPattern) { Write-Host "所有子串均符合模式" } else { Write-Host "存在不符合模式的子串" }
方法2:提取非法子串
处理空格后拆分字符串,筛选不符合规则的子串:
$cleanRange = $range -replace ',\s+', ',' $substrings = $cleanRange -split ',' $validPattern = '^(?:\d{1,4}|\d{1,4}-\d{1,4}|r\d{1,4}-r\d{1,4}|\d{1,4}-z|z-\d{1,4}|\d{1,4}-\d{1,4}:(?:odd|even))$' $invalidSubstrings = $substrings | Where-Object { $_ -notmatch $validPattern } if ($invalidSubstrings.Count -gt 0) { Write-Host "非法子串:$($invalidSubstrings -join ', ')" }
内容的提问来源于stack exchange,提问作者Tucker
相关产品推荐
相关产品推荐

