2

As a part of a buildscript in powershell, I am trying to extract a version number from a string using regular expression. The number is assumed to be in a format xx.yy (eg. 10.6) I need the Integer part (in this example, it would be 10) and the fraction part (example: 6)

I want to have a method that checks that both my patterns exists and thereafter extracts the numbers. (I am very much a novice in powershell, and am trying to avoid using C# functions, but rather powershell itself.)

I tried to do this:

$integralPart="A"
$fractionPart="B"

function GetVersion {
    param([string]$strVersion)
    $integralPattern="^[0-9]+(?=\.)" 
    $fractionalPattern="(?<=\.)[0-9]+$"

    #Check if string consists of an integral and fractional part
    If ($strVersion -match $integralPattern -eq $True -and $strVersion -match $fractionalPattern -eq $True)
    {
        $strVersion -match $integralPattern
        $integralPart = $matches[0]

        $strVersion -match $fractionalPattern
        $fractionalPart = $matches[0]
    } 
    else
    {
        Write-Host "You did not enter a double with an integer and a fractional part (eg. 10.6)"
        Exit
    }
}

GetVersion (Read-Host 'Enter program version')
Write-Host $integralPart
Write-Host $fractionPart

In doing so, I was hoping that $integralPart and $fractionalPart would contain my numbers, at they match the values they should

Can anyone explain how this can be done?

Bo Visfeldt
  • 77
  • 1
  • 7
  • What result do you get? – Wiktor Stribiżew Jan 13 '16 at 21:19
  • 2
    The problem is that the variables inside the function are not the ones you have declared at the top. Use solutions from [powershell setting a global variable from a function where the global variable name is a variable passed to the function](http://stackoverflow.com/questions/12535419/powershell-setting-a-global-variable-from-a-function-where-the-global-variable-n) – Wiktor Stribiżew Jan 13 '16 at 21:35
  • Ah, should have checked. $matches[0] actually DOES contains the right values.... but i must still do something wrong, as $integralPart and $fractionPart still end up with the values they were intitialized with – Bo Visfeldt Jan 13 '16 at 21:42

1 Answers1

3

You need to tell PS that the variables are from global scope with $global:

$integralPart="A"
$fractionPart="B"

function GetVersion {
    param([string]$strVersion)
    $integralPattern="^[0-9]+(?=\.)" 
    $fractionalPattern="(?<=\.)[0-9]+$"

    #Check if string consists of an integral and fractional part
    If ($strVersion -match $integralPattern -eq $True -and $strVersion -match $fractionalPattern -eq $True)
    {
        $strVersion -match $integralPattern
        $global:integralPart = $matches[0]   // SEE HERE

        $strVersion -match $fractionalPattern
        $global:fractionPart = $matches[0]   // SEE HERE
    } 
    else
    {
        Write-Host "You did not enter a double with an integer and a fractional part (eg. 10.6)"
        Exit
    }
}

GetVersion "10.6"
Write-Host $integralPart
Write-Host $fractionPart

Output:

True
True
10
6

Also, you have a typo: inside the GetVersion, you have $fractionalPart while the global variable is called $fractionPart.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    For things like this I'm a fan of casting the RegEx pattern as a `[RegEx]` type, and then doing a `$global:integralPart = $integralPattern.Matches($strVersion).value` kind of thing. Saves you the extra "True" output. – TheMadTechnician Jan 13 '16 at 22:06
  • @TheMadTechnician: I see but that would require some more changes with the code, I am not sure OP wants that. BTW, I think you meant `.Match` (not `.Matches`). @Bo Visfeldt: Does that work all right for you? – Wiktor Stribiżew Jan 13 '16 at 22:37
  • Instead of using globals you could save yourself a lot of future pain by adding the variables as parameters to the function. This also increases the functions reusability. – Bluecakes Jan 13 '16 at 23:10
  • Actually, I did mean Matches. The Match method only tells you True/False if it does match. The Matches method actually specifies what the matching substring is instead of doing Match, and then using the `$Matches` automatic variable. – TheMadTechnician Jan 13 '16 at 23:37
  • @TheMadTechnician: Ok, but it does not have `Value` property. It would be necessary to access the first match using the 0th index. – Wiktor Stribiżew Jan 13 '16 at 23:38
  • I beg to differ. Run `'ab12cd','ef34gh','ij56kl'|%{([regex]"\d{2}").matches($_).value}` and it will successfully extract the two digit number from the three strings provided. – TheMadTechnician Jan 13 '16 at 23:42