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.