Solved

Powershell Regex

Posted on 2013-06-06
8
364 Views
Last Modified: 2013-07-17
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?
0
Comment
Question by:VSI-O
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 40

Assisted Solution

by:Subsun
Subsun earned 375 total points
ID: 39227947
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
 
LVL 70

Assisted Solution

by:Qlemo
Qlemo earned 125 total points
ID: 39228225
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
 
LVL 40

Expert Comment

by:footech
ID: 39228376
@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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 70

Expert Comment

by:Qlemo
ID: 39228539
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
 
LVL 40

Assisted Solution

by:Subsun
Subsun earned 375 total points
ID: 39230851
@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
 
LVL 40

Expert Comment

by:footech
ID: 39231106
@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
 
LVL 40

Accepted Solution

by:
Subsun earned 375 total points
ID: 39231165
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
 
LVL 75

Expert Comment

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

Open in new window

0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will help you understand what HashTables are and how to use them in PowerShell.
A quick Powershell script I wrote to find old program installations and check versions of a specific file across the network.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question