Reputation: 8775
In PowerShell, how can I test if a variable holds a numeric value?
Currently, I'm trying to do it like this, but it always seems to return false
.
add-type -Language CSharpVersion3 @'
public class Helpers {
public static bool IsNumeric(object o) {
return o is byte || o is short || o is int || o is long
|| o is sbyte || o is ushort || o is uint || o is ulong
|| o is float || o is double || o is decimal
;
}
}
'@
filter isNumeric($InputObject) {
[Helpers]::IsNumeric($InputObject)
}
PS> 1 | isNumeric
False
Upvotes: 46
Views: 213320
Reputation: 16909
If you know the numeric type you want to test against (such as int
for example in the code below), you can do it like this:
> [bool]("42" -as [int])
True
> [bool](42 -as [int])
True
> [bool]("hi" -as [int])
False
But note:
> [bool]("42.1" -as [int])
True
Careful!:
It was pointed out that the code above fails to identify 0
as an int
. You would need to add a guard for 0
:
> $n -eq 0 -or $n -as [int]
Where $n
is the object you are testing.
Upvotes: 3
Reputation: 60918
Modify your filter like this:
filter isNumeric {
[Helpers]::IsNumeric($_)
}
function
uses the $input
variable to contain pipeline information whereas the filter
uses the special variable $_
that contains the current pipeline object.
Edit:
For a powershell syntax way you can use just a filter (w/o add-type):
filter isNumeric($x) {
return $x -is [byte] -or $x -is [int16] -or $x -is [int32] -or $x -is [int64] `
-or $x -is [sbyte] -or $x -is [uint16] -or $x -is [uint32] -or $x -is [uint64] `
-or $x -is [float] -or $x -is [double] -or $x -is [decimal]
}
Upvotes: 33
Reputation: 2201
Each numeric type has its own value. See TypeCode enum definition: https://learn.microsoft.com/en-us/dotnet/api/system.typecode?view=netframework-4.8 Based on this info, all your numeric type-values are in the range from 5 to 15. This means, you can write the condition-check like this:
$typeValue = $x.getTypeCode().value__
if ($typeValue -ge 5 -and $typeValue -le 15) {"x has a numeric type!"}
Upvotes: 2
Reputation: 302
$itisint=$true
try{
[int]$vartotest
}catch{
"error converting to int"
$itisint=$false
}
this is more universal, because this way you can test also strings (read from a file for example) if they represent number. The other solutions using -is [int] result in false if you would have "123" as string in a variable. This also works on machines with older powershell then 5.1
Upvotes: 4
Reputation: 11
"-123.456e-789" -match "^\-?(\d+\.?\d*)(e\-?\d+)?$|^0x[0-9a-f]+$"
or
"0xab789" -match "^\-?(\d+\.?\d*)(e\-?\d+)?$|^0x[0-9a-f]+$"
will check for numbers (integers, floats and hex).
Please note that this does not cover the case of commas/dots being used as separators for thousands.
Upvotes: 1
Reputation: 361
You can do something like :
$testvar -match '^[0-9]+$'
or
$testvar -match '^\d+$'
Returns True
if $testvar
is a number.
Upvotes: 36
Reputation: 424
filter isNumeric {
$_ -is [ValueType]
}
-
1 -is [ValueType]
True
"1" -is [ValueType]
False
-
function isNumeric ($Value) {
return $Value -is [ValueType]
}
isNumeric 1.23
True
isNumeric 123
True
isNumeric ""
False
isNumeric "asdf123"
False
-
(Invoke-Expression '1.5') -is [ValueType]
Upvotes: 7
Reputation: 65
Testing if a value is numeric or a string representation of a numeric value.
function Test-Number
{
Param
(
[Parameter(Mandatory=$true,
Position=0)]
[ValidatePattern("^[\d\.]+$")]
$Number
)
$Number -is [ValueType] -or [Double]::TryParse($Number,[ref]$null)
}
Testing if a value is numeric.
function Test-Number
{
Param
(
[Parameter(Mandatory=$true,
Position=0)]
[ValidatePattern("^[\d\.]+$")]
$Number
)
$Number -is [ValueType]
}
Upvotes: 0
Reputation: 21
I ran into this topic while working on input validation with read-host. If I tried to specify the data type for the variable as part of the read-host command and the user entered something other than that data type then read-host would error out. This is how I got around that and ensured that the user enters the data type I wanted:
do
{
try
{
[int]$thing = read-host -prompt "Enter a number or else"
$GotANumber = $true
}
catch
{
$GotANumber = $false
}
}
until
($gotanumber)
Upvotes: 2
Reputation: 813
If you want to check if a string has a numeric value, use this code:
$a = "44.4"
$b = "ad"
$rtn = ""
[double]::TryParse($a,[ref]$rtn)
[double]::TryParse($b,[ref]$rtn)
Credits go here
Upvotes: 18
Reputation: 47
Thank you all who contributed to this thread and helped me figure out how to test for numeric values. I wanted to post my results for how to handle negative numbers, for those who may also find this thread when searching...
Note: My function requires a string to be passed, due to using Trim().
function IsNumeric($value) {
# This function will test if a string value is numeric
#
# Parameters::
#
# $value - String to test
#
return ($($value.Trim()) -match "^[-]?[0-9.]+$")
}
Upvotes: 3
Reputation: 52430
PS> Add-Type -Assembly Microsoft.VisualBasic
PS> [Microsoft.VisualBasic.Information]::IsNumeric(1.5)
True
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.information.isnumeric.aspx
Upvotes: 14
Reputation: 35237
If you are testing a string for a numeric value then you can use the a regular expression and the -match
comparison. Otherwise Christian's answer is a good solution for type checking.
function Is-Numeric ($Value) {
return $Value -match "^[\d\.]+$"
}
Is-Numeric 1.23
True
Is-Numeric 123
True
Is-Numeric ""
False
Is-Numeric "asdf123"
False
Upvotes: 45
Reputation: 126752
-is and -as operators requires a type you can compare against. If you're not sure what the type might be, try to evaluate the content (partial type list):
(Invoke-Expression '1.5').GetType().Name -match 'byte|short|int32|long|sbyte|ushort|uint32|ulong|float|double|decimal'
Good or bad, it can work against hex values as well (Invoke-Expression '0xA' ...)
Upvotes: 11
Reputation: 1081
You can check whether the variable is a number like this: $val -is [int]
This will work for numeric values, but not if the number is wrapped in quotes:
1 -is [int]
True
"1" -is [int]
False
Upvotes: 64