PowerShell RegEx 拆分 MAC 地址

PowerShell RegEx to split MAC address

我需要使用 RegEx 验证 RAW 格式的 MAC 地址,并将其拆分为 6 个值和 2 个字符的数组。
当我使用以下模式时,我只获得捕获组最后一次迭代的内容:

PS C:\Windows\System32> "708BCDBC8A0D" -match "^([0-9a-z]{2}){6}$"
True
PS C:\Windows\System32> $Matches

Name                           Value
----                           -----
1                              0D
0                              708BCDBC8A0D


PS C:\Windows\System32>

用什么模式可以捕获所有组?
我需要这个结果:

0 = 708BCDBC8A0D
1 = 70
2 = 8B
3 = CD
4 = BC
5 = 8A
6 = 0D

您不能使用单个组定义捕获多个组。 避免在不必要时使用 RegEx,因为它需要很多 CPU。对数百万记录有价值。

对于 MAC,您可以使用特殊的 PhysicalAddress class:

[System.Net.NetworkInformation.PhysicalAddress]::Parse('708BCDBC8A0D') 

对于.Net 5(Powershell Core 我认为基于它)添加了TryParse方法,但是在.Net 4.5 没有 TryParse 方法。

要检查 .Net framework powershell 运行 使用 [System.Reflection.Assembly]::GetExecutingAssembly().ImageRuntimeVersion


'708BCDBC8A0D' -match "^$('([A-F0-9]{2})' * 6)$"; $Matches
'708BCDBC8A0D' -match '^([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$'; $Matches

'@(0..5) | ForEach-Object {'708BCDBC8A0D'.Substring($_ * 2, 2)}'

@(
    [String]::new('708BCDBC8A0D'[0..1]),
    [String]::new('708BCDBC8A0D'[2..3]),
    [String]::new('708BCDBC8A0D'[4..5]),
    [String]::new('708BCDBC8A0D'[6..7]),
    [String]::new('708BCDBC8A0D'[8..9]),
    [String]::new('708BCDBC8A0D'[10..11])
)

注意:我相信这个答案是正确的,并且希望对您有所帮助;如果您不同意,请告诉我们为什么

如您所见,automatic $Matches variable, which reflects the result of the most recent (scalar-input[1]) regular-expression-based match operation 仅包含嵌入式 捕获组last 实例((...)) 被捕获。

一般来说,-match只会在输入中寻找至多一个匹配项。

  • GitHub issue #7867 提议引入一个新的 -matchall 运算符,它将找到 all 匹配项并将它们 return 作为 数组.

Direct 使用 [regex] class (System.Text.RegularExpressions.Regex) 作为 PowerShell 正则表达式功能的基础已经提供了这种能力,在这种情况下捕获甚至不需要群组。

# Note: Inline option (?i) makes the regex case-INsensitive
#       (which PowerShell's operators are BY DEFAULT).
PS> [regex]::Matches('708BCDBC8A0D', '(?i)[0-9a-e]{2}').Value
70
8B
CD
BC
8A
0D

然而,稍加技巧,您也可以使用 -split,即 string splitting operator:

# Note: No inline option needed: -split - like -match and -replace -
#       is case-INsensitive by default.
PS> '708BCDBC8A0D' -split '([0-9a-e]{2})' -ne ''
70
8B
CD
BC
8A
0D

注:

  • 正则表达式必须包含在捕获组 (...) 中,以明确指示 -split 在结果中包含它匹配的内容;由于正则表达式通常描述感兴趣的子字符串之间的 分隔符,因此它的匹配项通常 包含。

  • 在这种情况下,只有我们关心的“分隔符”,而之间的子字符串是这里是空字符串,所以我们用-ne ''过滤掉它们。


[1] 如果 -match 操作的 LHS 是一个 数组(一个集合),匹配发生在 每个元素 和匹配元素的子数组(而不是单个布尔值)被 returned。在这种情况下,$Matches 填充。