我想检查字符串是否包含数值。我有这个代码:
$string = "some string that contains 123456 in the middle"
$substring = $string.substring(27,9).Trim()
我有 $substring 它将包含“123456”,我在这里找到了这个 IsNumeric 函数: 在 PowerShell 中,如何测试变量是否包含数值?
问题是,当我从 $string 中提取它时,它的行为就像字符串类型,而 IsNumeric 返回 false,因为它将它与所有数字类型进行比较。即使它包含一个数字,IsNumeric 的输出也将是 false。
有没有更好的方法来检查字符串是否包含数值?
可以使用正则表达式匹配来测试一下:
if($substring -match "^\d+$")
{
# Do something
}
这应该适用于仅包含数字(即正整数)的任何字符串。 如果您想包含负整数,请将模式更改为
^-?\d+$
。
检查给定字符串是否可以转换为数字的正确方法:
[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
}
然后
$OutNumber
将包含数字作为数字类型。
在正则表达式中 \d 是对数字的检查
\d* 检查 0 到无限数字
\d?检查 0 到 1 位数字
\d{0,5} 检查 0 到 5 位数字
\d+ 检查 1 到无限数字
^ 是一行的开头
$ 是行尾
所以
^\d+$ 将检查从行首到行尾的 1 个或多个数字,并且仅检查数字。任何其他符号都会破坏从头到尾的连接并且不会被发现。
使用
-as
type_operator 可能是最强大的 shell 方式。它将返回数字,如果无法转换则返回 $null
。为了使示例尽可能简短,我使用 int
但这也适用于 float
和 double
。例如:
"0" -as [int]
如果出于某种原因您only想检查字符串是否包含数字数据,那么您可以简单地通过
$null
针对
($null -ne ("0" -as [int]))
进行测试
但是,如果可能的话,您更有可能想要使用转换后的值,这很容易通过将结果分配给变量然后检查
$null
:来完成
$myNum = "0" -as [int]
if ($myNum -eq $null) {
#is not numeric
} else {
#is numeric
}
使用异常作为程序控制是一种非常糟糕的做法,并且可能保证您会看到性能的提高。
我还没有测试过这个断言,但我认为您很可能也会看到发布的正则表达式方法的性能有所提高,而且还有一个方便的数字。你可以使用带有分组的正则表达式来实现同样的事情,但还没有人发布:
"0" -match "(?<num>\d*)"
$Matches.num
加上你仍然实际上已经进行了转换:
$Matches.num.GetType()
([Int32]$Matches.num).GetType()
使用.NET框架的传统方式:
if( [Microsoft.VisualBasic.Information]::IsNumeric($myString) ) {
# do something
}
使用错误
它也接受小数。
[string]$myString = "12.3456"
try{
[int]$res=[int]1*$myString
Write-Host "Valid Number"
}catch{
Write-Host "Invalid Number"
}
这就是我测试字符串是否为数字的方法。 它考虑了数字文字格式,并且不需要转换为表示数字的几种数据类型中的任何一种。
function Test-StringIsNumber
{
[CmdletBinding()]
param (
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
#[System.String[]]$InputObject,
$InputObject,
[switch]$PassThru
)
process
{
foreach ($strValue in $InputObject)
{
$result = $false
$output = $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))
{
$output = Invoke-Expression -Command $strValue -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)
$obj = [pscustomobject] @{
InputObject = $strValue
ExpandedValue = $output
Type = $objType
IsNumber = $result
}
$outputObj = $obj
}
Write-Output $outputObj
}
} #process
} #function Test-StringIsNumber
结果:
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
使用 -match '\d'
string = "some string that contains 123456 in the middle"
$substring = $string.substring(27,9).Trim()
$substring -match '\d'