Search code examples
powershellcastingpowershell-7.0

Checking if a string can/cannot be converted to int/float


I am using PowerShell 7.1.4 and I wanna check if a string can be converted to a number.

Something like:

$age = Read-Host "age"

if(![int]$age) {
    Write-Host "$age is not a number"
}

I came from JavaScript so don't mind the "!" if its wrong, and I just started learning PowerShell.


Solution

  • You can use $age -as [int], which returns $null if conversion to the RHS type isn't possible, so that $null -eq ($age -as [int]) is only $true if the conversion is not possible (see -as, the conditional type conversion operator):

    if ($null -eq ($age -as [int])) { Write-Host "$age is NOT a number." }
    

    If you also want to save the converted value, you can take advantage of PowerShell's ability to use assignments as expressions:

    if ($null -eq ($ageNumber = $age -as [int])) { Write-Host "$age is NOT a number." }
    

    Caveat: -as and [int] casts convert the empty or blank (all-whitespace) strings (as well as $null) to 0. (Try '' -as [int], ' ' -as [int], and $null -as [int]).
    To avoid that:

    • either: use the .NET approach shown in the next section
    • or: add an additional check to detect these cases:
    if ('' -eq $age.Trim() -or $null -eq ($age -as [int])) { Write-Host "$age is NOT a number." }
    

    A less PowerShell-idiomatic, but stricter alternative would be to use the [int]::TryParse() .NET method:

    if (-not [int]::TryParse($age, [ref] $null)) { Write-Host "$age is NOT a number." }
    

    If you also want to save the converted value, initialize an output variable and pass it in lieu of $null:

    $ageNumber = $null  # Initialize the output variable (type doesn't matter).
    if (-not [int]::TryParse($age, [ref] $ageNumber)) { Write-Host "$age is NOT a number." }
    

    As implied above, this method does not recognize empty and blank strings as an integer.


    As for what you tried:

    ! is a valid PowerShell operator; its alias is -not

    • PowerShell implicitly converts its operand to a Boolean ([bool]), so a caveat with respect to integers is that ! 0 is also $true, even though 0 is a valid integer.

    • See the bottom section of this answer for an overview of PowerShell's implicit to-Boolean conversions.

    The problem is that an [int] cast causes a statement-terminating error when its operand can not be converted to the specified type. The use of the -as operator avoids this problem.

    For the sake of completeness: it is possible - though not advisable here - to use a try { ... } catch { ... } statement enclosed in $(), the subexpression operator, to catch the error:

    if ($null -eq $(try { [int] $age } catch {})) { Write-Host "$age is NOT a number." }