Kborvall
Kborvall

Reputation: 11

Powershell IF with multiple conditions not working

It's not making any sense. If I put this lines in my script it will still accept a number as 123 even if it's supposed to be just between 1 and 32. It's the line until ($setSubNetMask -cle 32 -and $setSubNetMask -cge 1) I'm having the problem with.

What's going on here?

do
{
    $setSubNetMask = 0
    $setSubNetMask = Read-Host -Prompt "Subnetmask (CIDR)" 
    if ($setSubNetMask -cge 32 -or $setSubNetMask -cle 2)
    {
        write-host "Felaktig CIDR (1-32)"
    }
}
until ($setSubNetMask -cle 32 -and $setSubNetMask -cge 1)

Upvotes: 1

Views: 672

Answers (2)

mjolinor
mjolinor

Reputation: 68273

As @briantist noted, it's due to the Read-Host returning a string value, and then comparing that to an [int].

When comparing dissimilar object types, Powershell will attempt to do the perform the operation by trying to cast the value on the RH side to match the type on the LH side. This means you can implicitly re-cast the strings to [int] by reversing the order of your comparison arguments so that the [int] is on the LH side:

do
{
    $setSubNetMask = 0
    $setSubNetMask = Read-Host -Prompt "Subnetmask (CIDR)" 
    if (32 -le $setSubNetMask -or 2 -gt $setSubNetMask)
    {
        write-host "Felaktig CIDR (1-32)"
    }
}
until (32 -le $setSubNetMask -and 1 -le $setSubNetMask)

Upvotes: 1

briantist
briantist

Reputation: 47792

Read-Host is giving you a string. You're comparing it to a number, which is being implicitly converted to a string because it's on the right side of the comparison.

What you want to do is convert to a number first:

do
{
    $setSubNetMask = 0
    [int]$setSubNetMask = Read-Host -Prompt "Subnetmask (CIDR)" 
    if ($setSubNetMask -cge 32 -or $setSubNetMask -cle 2)
    {
        write-host "Felaktig CIDR (1-32)"
    }
}
until ($setSubNetMask -cle 32 -and $setSubNetMask -cge 1)

PowerShell also supports ranges, so your conditionals might better be expressed as:

do
{
    $setSubNetMask = 0
    $setSubNetMask = Read-Host -Prompt "Subnetmask (CIDR)" 
    if (1..32 -notcontains $setSubNetMask)
    {
        write-host "Felaktig CIDR (1-32)"
    }
}
until (1..32 -contains $setSubNetMask)

In PowerShell v3 and higher, you can reverse the order using the -in operator instead of -contains, depending on what feels more natural to you:

do
{
    $setSubNetMask = 0
    $setSubNetMask = Read-Host -Prompt "Subnetmask (CIDR)" 
    if ($setSubNetMask -notin 1..32)
    {
        write-host "Felaktig CIDR (1-32)"
    }
}
until ($setSubNetMask -in 1..32)

Note that in these examples, I removed the [int] cast; it's not needed and the conversion will be done implicitly in either case.

Upvotes: 1

Related Questions