Powershell Regex

I need to extract a number from a string in Powershell. I will have a variable defined which contains text similar to this:

<VolumeInfo><VolumeInfoItem Name="F:" OriginalAccessPath="F:" State="14" HResult="0" DetailedHResult="0" PreviousState="9" IsCritical="0" IsIncremental="1" BlockLevel="0" HasFiles="1" 
HasSystemState="0" IsCompacted="0" IsPruned="0" IsRecreateVhd="0" FullBackupReason="0" DataTransferred="189367997" NumUnreadableBytes="0" TotalSize="189367997" TotalNoOfFiles="31" 
Flags="84" BackupTypeDetermined="1" SSBTotalNoOfFiles="0" SSBTotalSizeOnDisk="0" /></VolumeInfo>

Open in new window


I need to extract the number from DataTransferred="nnnnnnnnn" to a separate variable.
The number will vary in length.
I would prefer to use
$OutputString = select-string $Inputstring -InputObject $string1 -pattern "regex here"

Open in new window


What would my regex be?
VSI-OAsked:
Who is Participating?
 
SubsunConnect With a Mentor Commented:
Still not sure how -Split decide which property to take and process.. I have seen different behavior on different objects..

Here is some examples..


> $Test = Get-Service VSS | Select Status
> $Test.Status.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ServiceControllerStatus                  System.Enum
> $Test -split "="
@{Status
Stopped}


> $Test = Get-Service VSS | Select Status,Dis*
> $Test.Displayname.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
> $Test -split "="
@{Status
Stopped; DisplayName
Volume Shadow Copy}

> $Test = Get-Service | Select -First 2
> $Test

Status   Name               DisplayName
------   ----               -----------
Running  !SASCORE           SAS Core Service
Stopped  AdobeFlashPlaye... Adobe Flash Player Update Service

here it decide to take the name property and process it..
> $Test -split "Play"
!SASCORE
AdobeFlash
erUpdateSvc

> $Test = Get-Process | Select -First 2
> $Test

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    131       5     2476       4736    59            1828 atieclxx
    120       4     1840       2988    24            1360 atiesrxx

> $Test[0].processname.gettype()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

> $Test -Split "\."
System
Diagnostics
Process (atieclxx)
System
Diagnostics
Process (atiesrxx)
0
 
SubsunConnect With a Mentor Commented:
Try...
$String = '<VolumeInfo><VolumeInfoItem Name="F:" OriginalAccessPath="F:" State="14" HResult="0" DetailedHResult="0" PreviousState="9" IsCritical="0" IsIncremental="1" BlockLevel="0" HasFiles="1" 
HasSystemState="0" IsCompacted="0" IsPruned="0" IsRecreateVhd="0" FullBackupReason="0" DataTransferred="189367997" NumUnreadableBytes="0" TotalSize="189367997" TotalNoOfFiles="31" 
Flags="84" BackupTypeDetermined="1" SSBTotalNoOfFiles="0" SSBTotalSizeOnDisk="0" /></VolumeInfo>'

$OutputString = select-string -InputObject $string -pattern 'DataTransferred="\d+"' | %{($_.Matches -split '"')[1]}

$OutputString

Open in new window

0
 
QlemoConnect With a Mentor Batchelor, Developer and EE Topic AdvisorCommented:
I would use XML parsing instead - more straight-forward:
$xml = [xml] '<VolumeInfo><VolumeInfoItem Name="F:" OriginalAccessPath="F:" State="14" HResult="0" DetailedHResult="0" PreviousState="9" IsCritical="0" IsIncremental="1" BlockLevel="0" HasFiles="1" 
HasSystemState="0" IsCompacted="0" IsPruned="0" IsRecreateVhd="0" FullBackupReason="0" DataTransferred="189367997" NumUnreadableBytes="0" TotalSize="189367997" TotalNoOfFiles="31" 
Flags="84" BackupTypeDetermined="1" SSBTotalNoOfFiles="0" SSBTotalSizeOnDisk="0" /></VolumeInfo>'

$DataTransferred = $xml.VolumeInfo.VolumeInfoItem.DataTransferred

Open in new window

0
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 
footechCommented:
@Qlemo - Nice catch on the XML format.  I'll have to remember to keep an eye out for that.

@Subsun - How did you figure out the "...| %{($_.Matches -split '"')[1]}" syntax, specifically that the split would work at that point?  To get to a value I've always done something like "...| %{$_.Matches} | %{$_.Value}" (after which I could do a split, etc.).
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Looking detailed for the regex, I'll rather use this, which also can cope with an array of strings:
$String = '<VolumeInfo><VolumeInfoItem Name="F:" OriginalAccessPath="F:" State="14" HResult="0" DetailedHResult="0" PreviousState="9" IsCritical="0" IsIncremental="1" BlockLevel="0" HasFiles="1" 
HasSystemState="0" IsCompacted="0" IsPruned="0" IsRecreateVhd="0" FullBackupReason="0" DataTransferred="189367997" NumUnreadableBytes="0" TotalSize="189367997" TotalNoOfFiles="31" 
Flags="84" BackupTypeDetermined="1" SSBTotalNoOfFiles="0" SSBTotalSizeOnDisk="0" /></VolumeInfo>'

$DataTransferred = $string | % {if ($_  -match '\w*DataTransferred="(\d+)".*') {$matches[1]}} 

Open in new window

0
 
SubsunConnect With a Mentor Commented:
@footech, I had used it in many of my codes, that's why I know it works.. :-) ...  If you're looking for a technical explanation... I think, by default -split accepts the Matches value property (captured substring from the input string) and process it.. But I could not find any reference to justify the reason.. If I find something I will post it here.. or may be Dr Qlemo can explain about it..

Other options which I can think of to get the same result is..
$OutputString = If ($string -match 'DataTransferred="(\d+)"') {$matches[1]}

Open in new window

or
[regex]$regex = 'DataTransferred="(\d+)"'
$OutputString = $regex.Matches($String) | % {$_.Groups[1].Value}

Open in new window

0
 
footechCommented:
@Subsun - I've no doubt that it works, it's just that I'd never seen -split used directly on a RegEx Match object, and was surprised to see it given that the Match object isn't a string.  Maybe it works because Value is the only property of a Match object that is a string, so perhaps if an object is passed to the split operator it works on any properties that are strings.

Here's another variation (essentially just different syntax for your last)
$OutputString = [regex]::match($string,'DataTransferred="(\d+)"') | %{$_.groups[1].value}

Open in new window

0
 
käµfm³d 👽Commented:
Try:
-pattern "(?<=DataTransferred=`")\d+"

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.