Поделиться через


The “Joy” of Reg-ex part 2 – ways I use it

In the previous post I gave some of the background to regular expression and how they might be used. I thought I’d give a few examples.

1. Checking paths.

Quite a few of my functions take paths to Hyper-V virtual hard disk files as parameters and I don’t want to force the user to type “.VHD”, so I also have a check

 if ($Path -notmatch "VHD$") {$path += ".VHD"}            

If the path doesn’t end with VHD , add VHD to the end of it, and I also don’t want to make the user type in the default path so I used to have this in many places. I had variations of this line in many places:

 if ((Split-Path $Path) -eq "") {$Path = Join-Path $Default $Path }

It Checks to see if a path parameter is actually just a file name, if it is , it adds a default path to the front of it.  There’s only one problem  - the path might be on a remove server, and might not exist on the local server. That never affected me in testing but one of my users discoverd that PowerShell’s Split-Path tries to be helpful but might come back with

 Split-Path : Cannot find drive. A drive with the name 'E' does not exist.

Not what I want at all - I’m actually testing for is “is there a letter followed by a colon OR a characters followed by a \ followed by another characters”, in regex terms this is "(\w:|\w)\\\w" – it helps to read it aloud as “(word=character colon OR word-character) backslash-character word-character” - so my line morphs into:

 if ($Path -notmatch "(\w:|\w)\\\w") {$Path = Join-Path $Default $Path }

There is a simpler case when people are attaching the a host DVD to a virtual drive in a Hyper-V. I want to people to have to find the internal drive path windows uses for the drive, I just want them to be able to say D: so the test is for “Start word-character colon end” like this

 if ($path -match "^\w:$") {$path = Get-WmiObject etc }

2. Building lists into separated strings

Quite often you have a need to loop through something building up a list with commas or semi-colons or whatever between the items. And you need to deal with the empty strings, and making sure you don’t have a dangling separator at the end

 $BootOrder | foreach-object -begin {$bootDevices=""}`
                          -process {$bootdevices += ([bootmedia]$_).tostring() +","} `
                              -end {$bootDevices -replace ",$","" }            

I have bootmedia enum type which converts 0,1,2,3 into CD,Network,Floppy,IDE disk. The loop first sets up an empty string then converts each item using the enum type, and adds a comma. Finally it returns the string with the trailing comma lopped off.

3. Simplifying an or

Sometimes you want to do something if a piece of text is one of multiple values ,for example don’t do something on the core or Hyper-V installations which you would do a full server installation. Some  people would would write this as

 $regpath     = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"            
$regProps    = Get-Itemproperty -Path $regpath            
$WinEdition  = $regprops.editionid            
$Coreinstall = ($winEdition -like "*core*" )
$HyperVSku   = ($winEdition -like "*hyper*") 
if ( -not ($CoreInstall –or $HyperVSku ) 

But this can be compacted into a much easier to read version

 $regProps = Get-Itemproperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"                        
if ( $regprops.editionid  -notmatch "core|hyper") {"boo"}            

or even, single line

 
 if ((Get-Itemproperty -path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion").editionID -notmatch "core|hyper") 
  

I said at the end of the previous post I was going to cover “one of the best tools in PowerShell – select string.” that will actually be in part 3.