17

I want to check if a string contains a numeric value. I have this code :

$string = "some string that contains 123456     in the middle"
$substring = $string.substring(27,9).Trim()

I have $substring which will be containing "123456" and I found this IsNumeric function here : In PowerShell, how can I test if a variable holds a numeric value?

The thing is that this when I'm extracting it from $string it acts like string type and IsNumeric returns false since it's comparing it to the all numeric types. and even tough it will contain a number the output of IsNumeric will be false.

Is there a better way to check if string contains numeric values?

8 Answers 8

28

You can use a regular expression match to test it:

if($substring -match "^\d+$")
{
   # Do something
}

This should work for any string which contains only digits (i.e. is a positive integer). Change the pattern to ^-?\d+$ if you want to include negative integers.

Sign up to request clarification or add additional context in comments.

Comments

19

The correct way to check if a given string can be turned into a number:

[string]$InString = "123456"
[Int32]$OutNumber = $null

if ([Int32]::TryParse($InString,[ref]$OutNumber)){
    Write-Host "Valid Number"
    $OutNumber
} else {
    Write-Host "Invalid Number"
    #error code here
}

then $OutNumber will contain the number as a numeric type.

Comments

11

In regex \d is the check for digits

\d* checks for 0 to infinite digits

\d? Checks for 0 to 1 digit

\d{0,5} checks for 0 to 5 digits

\d+ checks for 1 to infinite digits

^ is the beggining of a line

$ is the end of a line

So

^\d+$ will check for 1 or more digits from the beginning to the end of the line and only digits. Any other symbol will break the connection from beginning to end and not be found.

Comments

6

Using the -as type_operator is probably the most powershell way. It will return the number, or $null if it was not possible to convert. To keep the examples as short as possible I am using int but this will work for float and double as well. For example:

"0" -as [int]

If for some reason you only wanted to check if the string contains numeric data then you could simply test this against $null via ($null -ne ("0" -as [int]))

But it's probably far more likely that you will want to use the value once converted, if possible, which is easily done by just assigning the result to a variable then checking against $null:

$myNum = "0" -as [int]
if ($myNum -eq $null) {
    #is not numeric
} else {
    #is numeric
}

Using exceptions as program control is a very bad practice, and likely a guarantee that you will see a performance increase with this over that.

I haven't tested this assertion, but I think it is very likely you will also see a performance increase over the regex method posted as well, with the bonus of also having the number handy. You could use a regex with grouping to achieve the same thing, but nobody has posted that yet:

"0" -match "(?<num>\d*)"
$Matches.num

Plus you still have actually do the conversion:

$Matches.num.GetType()
([Int32]$Matches.num).GetType()

1 Comment

To avoid temporary variable if (("24" -as [int]) -is [int])
4

The traditional way using the .NET framework:

if( [Microsoft.VisualBasic.Information]::IsNumeric($myString) ) {
  # do something
}

2 Comments

Add-Type -AssemblyName Microsoft.VisualBasic; Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a';
This has a small issue with dollar amounts. If I used this it passes for '$42', but later when I attempt to cast to [int] PowerShell throws an error.
0

using error

It's accepts decimal numbers too.

[string]$myString = "12.3456"
try{
    [int]$res=[int]1*$myString
    Write-Host "Valid Number"
}catch{
    Write-Host "Invalid Number"
}

Comments

0

Testing if a string "contains a numeric value/number" will demand different criteria depending on the use case:

  • Use regex for: Testing if a string simply contains digits (and possibly also any appropriate puncuation/formatting) that ultimately represents a number or numeric value to a person. Each of these examples can represent a numeric value to a person, but not necessarily to a parser/compiler/interpreter:
    • $5.99
    • 18236E+9
    • (Nine cubed)
    • 111 (Is this a decimal string? Binary string?)
    • 0b1 (Is this binary notation or a string?).
    • e (Is this an italicized e or does it represent Euler's number?)
    • π (Does this need to be approximated and represented as a rational number? Is it just the lowercase varient of Π rather than the mathematical constant?)
    • 2x4 (Is this multiplication? Is it a time signature? Is it a piece of lumber?)
    • 2*4 (Is this multiplication? Is it a glob pattern? Is it lumber again??)
  • Note that a numeric string might not be usable as a number type in .NET in terms of exceeding integral type MinValue/MaxValue limits.
  • The BigInteger type offers capabilities for numeric string evaluations concerned with usable numeric values which exceed other integral type limits.
  • See also: What is the maximum possible length of a .NET string?


This is how I test if a string is a number.
  • It accounts for numeric literal format(s)/expressions and doesn't require casting to any of the several data types that represent numbers.
  • PowerShell's parsing engine is the limiting factor in determining the upper/lower bounds of a numeric literal expression, therefor the limiting factor in the min/max values allowed for this function.
  • This function could be altered to leverage the TryParse() method of the bigint type.
function Test-StringIsNumber
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
        [ValidateNotNullOrEmpty()]
        $InputObject,

        [switch]$PassThru
    )

    process
    {
        foreach ($strValue in $InputObject)
        {
            $result = $false
            $output = $strValue
            $input = $strValue

            try
            {
                # Check Get-Command first to make sure that Invoke-Expression doesn't actually run something.
                # Even if a cmdlet or function has a name that's a numeric literal (e.g. function 5GB {throw "!"}), the literal will be parsed first.
                if ($null -eq (Get-Command -Name $strValue -ErrorAction Ignore))
                {
                    # Trim any leading and trailing quotes so Invoke-Expression doesn't execute a string literal and falsely identify it as a number.
                    $iexCommand = $strValue.TrimStart("'", '"').TrimEnd("'", '"')
                    $output = Invoke-Expression -Command $iexCommand -ErrorAction Stop

                    # $strValue is a number or uses numeric literal formatting.
                    $result = $true
                }
            } catch {}

            $outputObj = $result

            if ($PassThru)
            {
                $objType = [System.Type]::GetType($output.GetType().FullName)

                $outputObj = [pscustomobject] @{
                    InputObject = $input
                    ExpandedValue = $output
                    Type = $objType
                    IsNumber = $result
                }
            }

            Write-Output $outputObj
        } #foreach
    } #process
} #function Test-StringIsNumber



Results:

PS C:\> Test-StringIsNumber '0xf'
True

PS C:\> Test-StringIsNumber '0xh'
False

PS C:\> Test-StringIsNumber '500.9L'
True

PS C:\> Test-StringIsNumber '100gbL'
False

PS C:\> Test-StringIsNumber 1.79769313486232E+11 -PassThru

         InputObject    ExpandedValue Type          IsNumber
         -----------    ------------- ----          --------
1.79769313486232E+11 179769313486.232 System.Double     True

PS C:\> Test-StringIsNumber '-0xbadf00d' -PassThru

InputObject ExpandedValue Type         IsNumber
----------- ------------- ----         --------
-0xbadf00d     -195948557 System.Int32     True

PS C:\> Test-StringIsNumber '0xg00df00d' -PassThru

InputObject ExpandedValue Type          IsNumber
----------- ------------- ----          --------
0xg00df00d  0xg00df00d    System.String    False

PS C:\> Test-StringIsNumber "'Test String'"
False

Comments

-1

use -match '\d'

string = "some string that contains 123456     in the middle"
$substring = $string.substring(27,9).Trim()
$substring -match '\d'

3 Comments

It actually returns true for every type of substring that I've tried. Even with letters and numbers mixed together
@MarkedOne the regex here should have been ^\d+$ to say 'only numbers' rather than just 'contains at least one number'.
"Is there a better way to check if string contains numeric value?" I read this as a string may contain a numeric value not only numeric values :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.