1

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.

invisible boi
  • 106
  • 1
  • 8
  • `![int]$age` is a perfectly valid expression in PowerShell, but it will accept/cast _any_ string that can be converted to `[int]` in PowerShells grammar, which may not fit your strict definition of "number" :) Try `[int]''`, `[int]'1e4'`, `[int]'30s'`, `[int]'0xAB'` – Mathias R. Jessen Oct 08 '21 at 18:43
  • Hello! All input taken by `Read-Host` is of type *string*, unless explicitly specified to type `[int]`. Such as `$age = (Read-Host -Prompt "age") -as [int]`, or casting the type: `[int]$age`. In other words, you can type constrain it to explicitly be of type `[int]` – Abraham Zinala Oct 08 '21 at 18:44
  • Does this answer your question? [In Powershell what is the idiomatic way of converting a string to an int?](https://stackoverflow.com/questions/9700627/in-powershell-what-is-the-idiomatic-way-of-converting-a-string-to-an-int) – OwlsSleeping Oct 08 '21 at 18:47

1 Answers1

4

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." }
mklement0
  • 382,024
  • 64
  • 607
  • 775