【问题标题】:Powershell - Regular Expression Multiple MatchesPowershell - 正则表达式多重匹配
【发布时间】:2014-09-10 04:55:53
【问题描述】:

也许我的推理有问题,但我无法让它发挥作用。

这是我的正则表达式:(Device\s#\d(\n.*)*?(?=\n\s*Device\s#|\Z))

试试看:http://regex101.com/r/jQ6uC8/6

$getdevice 是输入字符串。我从命令行工具的流/输出中获取此字符串。

$dstate = $getdevice |
     select-string -pattern '(Device\s#\d(\n.*)*?(?=\n\s*SSD\s+|\Z))' -AllMatches |
     % { $_ -match '(Device\s#\d(\n.*)*?(?=\n\s*SSD\s+|\Z))' > $null; $matches[0] }
Write-Host $dstate

输出:

设备#0 设备#1 设备#2 设备#3 设备#4

$matches[1] 的输出相同,$matches[2] 为空。

有没有办法让我获得所有匹配项,例如在 regex101.com 上?我正在尝试将输出/字符串拆分为单独的变量(一个用于 Device0,一个用于 Device1、Device2 等)。

更新:以下是命令行工具的输出:http://pastebin.com/BaywGtFE

【问题讨论】:

标签: regex powershell powershell-4.0 regex-group


【解决方案1】:

我在此处的字符串中使用了您的示例数据进行测试。这应该可以工作,尽管它可能取决于您的样本数据来自哪里。

使用 powershell 3.0 我有以下内容

$getdevice | 
    select-string -pattern '(?smi)(Device\s#\d+?(.*?)*?(?=Device\s#|\Z))' -AllMatches | 
    ForEach-Object {$_.Matches} | 
    ForEach-Object {$_.Value}

或者如果您的 PowerShell 版本支持它...

($getdevice | select-string -pattern '(?smi)(Device\s#\d+?(.*?)*?(?=Device\s#|\Z))' -AllMatches).Matches.Value

返回 4 个对象及其设备 ID。我不知道您是否想要这些,但如果您不需要这些,可以使用环视来修改正则表达式。我更新了正则表达式以说明设备 ID 的位数超过一位,以防发生这种情况。

我使用的修饰符

  1. s 修饰符:单行。点匹配换行符
  2. m 修饰符:多行。导致 ^ 和 $ 匹配每行的开始/结束(不是 仅字符串的开头/结尾)
  3. i 修饰符:不敏感。不区分大小写的匹配(忽略 [a-zA-Z] 的大小写)

另一种以这种方式工作的正则表达式模式更短

'(?smi)(Device\s#).*?(?=Device\s#|\Z)'

【讨论】:

  • 嗨@Matt。这是迄今为止我的问题的最佳答案,它就像我提供的测试字符串的魅力一样!谢谢 !!无论如何,我对实时数据有同样的问题(对我来说看起来一样......)我只是回到了比赛的第一行。例如Device #0Device #1
  • 我认为它与换行或回车有关。也许我也需要转换命令行工具/exe的输出。我的字符串存储在这里$getdevice = .\arcconf.exe getconfig $cid PD 无论如何输出看起来相同
  • 刚刚找到解决方案。我通过管道输出槽Out-Sting 示例:$getdevice = .\arcconf.exe getconfig $cid PD | Out-String 现在它正在工作。
【解决方案2】:

使用您现有的正则表达式,要获取字符串中所有匹配项的列表,请使用以下选项之一:

选项 1

$regex = [regex] '(Device\s#\d(\n.*)*?(?=\n\s*Device\s#|\Z))'
$allmatches = $regex.Matches($yourString);
if ($allmatches.Count > 0) {
    # Get the individual matches with $allmatches.Item[]
} else {
    # Nah, no match
} 

选项 2

$resultlist = new-object System.Collections.Specialized.StringCollection
$regex = [regex] '(Device\s#\d(\n.*)*?(?=\n\s*Device\s#|\Z))'
$match = $regex.Match($yourString)
while ($match.Success) {
    $resultlist.Add($match.Value) | out-null
    $match = $match.NextMatch()
} 

【讨论】:

  • 您的帮助。无论如何,我不能让它与我的数据一起使用。匹配数组始终为空。也会尝试找出问题所在。
【解决方案3】:

虽然它不能完全回答您的问题,但我将提供一种稍微不同的方法:

($getdevice)  -split '\s+(?=Device #\d)' | select -Skip 1

只是为了好玩,

$drives = 
($getdevice)  -split '\s+(?=Device #\d)' | 
select -Skip 1 |
foreach { $Stringdata = 
          $_.replace(' : ','=') -replace 'Device #(\d)','Device = $1' -Replace 'Device is a (\w+)','DeviceIs = $1'
          New-Object PSObject -Property  $(ConvertFrom-StringData $Stringdata)
          } 

$drives | select Device,DeviceIs,'Total Size'

Device                             DeviceIs                           Total Size                        
------                             --------                           ----------                        
0                                  Hard drive                         70007 MB                          
1                                  Hard drive                         70007 MB                          
2                                  Hard drive                         286102 MB                         
3                                  Hard drive                         286102 MB                

【讨论】:

  • 将字符串转换为哈希和嵌套替换的出色工作,从而将其格式化为一个非常通用的对象。这向我展示了如何使用 PSObjectConvertFrom-StringData
  • 哇,没想到这么好的解决方案。无论如何,我在“实时”输入/字符串中遇到了一些错误。 pastebin.com/0uChjGa1。但它与我提供的示例输出/字符串一起使用,所以答案是正确的。只需要弄清楚问题,如果我可以继续使用该答案/解决方案。 ty
  • 也发布了 Matts 答案.. 我通过Out-String 通过管道输出命令行,现在输出看起来更好更正确。无论如何,我有一个错误。 ConvertFrom-StringData : Datenzeile " Device is an Enclosure services device" weist nicht das "Name=Wert"-Format auf. 不知道如何摆脱它,我不知道 Device is an Enclosure services device 字符串有什么不同。
  • 对垃圾评论感到抱歉-但我想通了。它的替换字符串很简单,您搜索“Device is a”,在该特殊输出中它的“Device is a n”。刚刚调整了-replace,现在它的工作发现。 ty
【解决方案4】:

试试这个变种:

[regex]::Matches($data,'(?im)device #\d((?!\s*Device #\d)\r?\n.)*?') | select value

Value
-----
Device #0
Device #1
Device #2
Device #3
Device #4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多