2017-03-31 102 views
1

鉴于串指定字符串

RAM Statistics: 5954/8174 743=InUse 746=Peak 

我需要一个正则表达式(或三个)以提取743,所述746,理想的5954/8174因此每个可以分配给一个特定的变量之前获取数。例如,我认为这是LookBehind的用途,但实际上我得到了一个RegEx来“获取空格和=峰值之间的数字”。

我已经试过

$string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
$regexPeak = '(?<=)(.#)(?=\=Peak)' 
$string -match $regexPeak > $null 
$peak = $matches[0] 
Write-Host "$peak" 

但是,这回什么。

UPDATE: 每约书亚我已经试过

$string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
$regexPeak = '(\d+)/(\d+) (\d+)=\D+(\d+)=peak/gi' 
$string -match $regexPeak 
$peak = $matches[0] 
Write-Host "$peak!" 

而且两者$比赛[0]和[1]返回=峰值之前的一切。所以

Statistics:  5954/ 8174  743=InUse  746! 
+0

也许'$串| select-string -pattern'\ d +(?:\ s */\ s * \ d +)?' -AllMatches | Foreach {$ _。Matches} | ForEach-Object {$ _。Value}'会做,如果你只需要一个可选的'/'+数字的数字。 –

回答

1

刚刚拉开试用代码:

$string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
$regexPeak = '(?<=)(.#)(?=\=Peak)' 

你的正则表达式有一个空间,这是OK了回顾后。然后它有一个中间位,分组为(.#),几乎可以肯定没有按照你的意图去做 - 点匹配任何单个字符,而散列匹配散列。所以它会匹配4#z###而不是746。然后你有一个积极的lookahead,这看起来不错。但综合效果是将内部位锁定为两个字符并寻找space, two characters (where the second is a hash), equals peak

也许你想\d是指一个数字,并+意味着“匹配一次或多次”,所以\d+

你正在做的第二件事是混合了lookarounds和分组。正则表达式的一种用法是将类似'number is 4'这样的字符串与像'number is (\d)'这样的模式相匹配。整个模式匹配并显示在输出中,然后您查询捕获组以挑选整个匹配中的4$matches[0]number is 4$matches[1]4

正则表达式的另一种用法涉及将数字与向后看像如(?<=number is)\d匹配,因为lookbehind匹配但它不出现在输出中。所以$matches[0]的输出只是4,你不需要任何组。所以你使用lookarounds来匹配没有在输出中的文本,并尝试将数字分组,并且这种方法可行,但这是过度/不必要的混合使用两种不同的方法。

这意味着您的正则表达式是非常接近的工作:

$regexPeak = '(?<=)(.#)(?=\=Peak)' # change to 
$regexPeak = '(?<=)\d+(?=\=Peak)' # to indicate "one or more digits" 

和:

PS C:\> $string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
PS C:\> $regexPeak = '(?<=)\d+(?=\=Peak)' 
PS C:\> $string -match $regexPeak > $null 
PS C:\> $peak = $matches[0] 
PS C:\> $peak 
746 
+1

谢谢!这正是我需要的。凭借这种见解,我得到了比率提取代码。我只需要搜索适当的数字格式就是一个'Doh!'的事实。时刻。 – Gordon

0

更新正则表达式:
/(\d+) \/ (\d+) (\d+)=\D+(\d+)=peak/gi

+0

Joshua,我发现实际的InUse和Peak文本没有包含在RegEx中。我怀疑这可能是一个问题,因为我不能相信字符串的格式和内容。我不控制它,我解析别人的文件,他们警告我他们的“不一致性”。所以我怀疑只有一个正则表达式可以找到“空格和峰值之间的数字”。 – Gordon

+0

好的,我会调整。 –

+0

我是根据你的说法做出来的,让我知道这是否适合你。 –

2
$Pattern = '(\d+) *\/ *(\d+) +(\d+)=[^0-9]*(\d+)' 
$string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
if ($string -match $Pattern){$Matches[0..4]} 

5954/ 8174  743=InUse  746 
5954 
8174 
743 
746 
+0

LotPings,问题是我不知道我可以信任山顶跟随InUse,或两者遵循口粮,或其他值不显示。所以,任何依赖于找到四个数字的东西,前两个都会产生一个比率,第三个是InUse,第四个是Peak将会出现错误。在一个完美的世界中,每个值都是一个行项目,但Autodesk并没有这样做,因为我猜他们从未期望任何人实际使用他们生产的大量数据。 – Gordon

+0

你应该在你的问题中包含这些额外的限制。 – LotPings

+0

嗯,我在第一篇文章中说过“在空格和=高峰之间获取数字”,因为我预计需要这个限制。但是,我应该解释为什么我特别。 – Gordon

0

其他的方法,没有正则表达式

[email protected]" 
{Data:RAM Statistics:{RamStat: 123456/ 123}  {InUseValue:743}=InUse  {PeakValue:746}=Peak} 
"@ 

$string = 'RAM Statistics:  5954/ 8174  743=InUse  746=Peak' 
$result=$string | ConvertFrom-String -TemplateContent $Template 

write-host "RamStat : " $result.Data.RamStat 
write-host "PeakValue : " $result.Data.PeakValue 
write-host "InUseValue : " $result.Data.InUseValue 
0

具有更复杂雷杰另一个答案x与命名组在regex101.com上工作,但与脚本失败。我猜是由于RegEx实现的差异。

$string = @' 
RAM Statistics:  1954/ 8174  743=InUse  746=Peak 
RAM Statistics:  2954/ 8174  746=Peak 
RAM Statistics:  3954/ 8174  743=InUse 
RAM Statistics:  4954/ 8174 
'@ 

$Pattern = '(?sm)^RAM Statistics: *(?<Ram>\d+) *\/ *(?<Ratio>\d+)(*(?<InUse>\d+)=InUse)?(*(?<Peak>\d+)=Peak)?' 

$string.split('`n') |ForEach{ 
    $_ -match $Pattern|out-null 
    "RAM {0}/{1} {2} InUse {3} Peak" -f $Matches.Ram,$Matches.Ratio,$Matches.InUse,$Matches.Peak 
} 

RAM 1954/8174 InUse Peak 
RAM 2954/8174 InUse 746 Peak 
RAM 4954/8174 InUse Peak 
0

好吧,稍微不同的方式在这里,使用正则表达式对象,而不是-match操作。既然你提到了不一致,我已经运行了两次,一次添加了垃圾文本和额外的空白,一次只有一些存在的项目。

$MyRegEx = ([regex]'\b(?<peak>\d+)(?=\=Peak)|(?<ratio>\d+\s*\/\s*\d+)|\b(?<inuse>\d+)(?=\=InUse)') 
$String='RAM Statistics: 5954/8174 1=somegarbage 743=InUse    746=Peak' 
$Results=$MyRegex.matches($String) 
Switch($Results){ 
    {$_.groups['ratio'].success}{"Ratio = " + $_.Groups['ratio'].value} 
    {$_.groups['inuse'].success}{"InUse = " + $_.Groups['inuse'].value} 
    {$_.groups['peak'].success}{"Peak = " + $_.Groups['peak'].value} 
} 

$String2 = 'RAM Statistics: 5954/8174 746=Peak' 
$Results=$MyRegex.matches($String2) 
Switch($Results){ 
    {$_.groups['ratio'].success}{"Ratio = " + $_.Groups['ratio'].value} 
    {$_.groups['inuse'].success}{"InUse = " + $_.Groups['inuse'].value} 
    {$_.groups['peak'].success}{"Peak = " + $_.Groups['peak'].value} 
} 

,将让你的结果:

Ratio = 5954/8174 
InUse = 743 
Peak = 746 

,并在第二个字符串:

Ratio = 5954/8174 
Peak = 746 

这是通过使用命名捕获组,然后评估结果看完成如果该捕获组在特定分组中成功。我用Switch完成了。

0
[regex]::Matches('RAM Statistics: 5954/8174 743=InUse 746=Peak','\D+(\d+)')|%{$_.groups[1].value} 

它给人的下一个结果::

5954 
8174 
743 
746