10

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

这是我的正则表达式:(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

4

4 回答 4

16

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

使用 powershell 3.0 我有以下

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

或者如果您的 PowerShell Verison 支持它...

($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)'
于 2014-07-19T01:48:59.333 回答
6

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

选项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()
} 
于 2014-07-19T00:25:58.327 回答
2

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

($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                
于 2014-07-19T00:53:03.803 回答
1

试试这个变种:

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

Value
-----
Device #0
Device #1
Device #2
Device #3
Device #4
于 2014-07-19T10:20:32.550 回答