【问题标题】:PowerShell RegEx to split MAC addressPowerShell RegEx 拆分 MAC 地址
【发布时间】:2021-06-18 20:46:24
【问题描述】:

我需要使用 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

【问题讨论】:

  • 这能回答你的问题吗? Input HEX as a string
  • [System.Net.NetworkInformation.PhysicalAddress]::Parse('708BCDBC8A0D').GetAddressBytes() |% ToString X2
  • 看起来@iRon 的链接回答了这个问题。

标签: regex powershell mac-address capture-group


【解决方案1】:

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

正如您所观察到的,automatic $Matches variable 反映了最近的(标量输入[1]regular-expression-based match operation 的结果,它只包含 last 嵌入式捕获组 ((...)) 捕获的实例。

通常,-match 在输入中只查找 最多一个 匹配项。

  • GitHub issue #7867 建议引入一个新的 -matchall 运算符,该运算符将查找 所有 匹配项并将它们作为 array 返回。

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

# 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

不过,有一点技巧,你也可以使用-splitstring 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 在结果中包含匹配的内容;由于正则表达式通常描述了感兴趣的子字符串之间的分隔符,因此它的匹配通常包括在内。

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


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

【讨论】:

    【解决方案2】:

    您不能使用单个组定义捕获多个组。 不必要时避免使用 RegEx,因为它会占用大量 CPU。价值数百万的记录。

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

    [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])
    )
    

    【讨论】:

    • 我知道使用 RegEx 时 CPU 负载会更高,但无论如何我都需要它来验证 MAC 地址。用* 6“破解”最好不要重复定义。还有这种 PowerShell 方式@(0..5) | ForEach-Object {'708BCDBC8A0D'.Substring($_ * 2, 2)}。感谢您的提示!
    • 也许在你的情况下使用[System.Net.NetworkInformation.PhysicalAddress]::Parse('708BCDBC8A0D') 更好?
    • 关于PowerShell版本底层的.NET版本:从当前稳定版本PowerShell 7.1.3开始,为.NET 5.0.4。 v7.2 可能基于 .NET 6.0(尚未发布)。您可以在 PowerShell(核心)会话中运行以下命令来确定底层 .NET 版本:(ConvertFrom-Json (Get-Content -Raw "$PSHOME/pwsh.runtimeconfig.json")).runtimeOptions.includedFrameworks.version
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多