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
未 填充。
我需要使用 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
未 填充。