在PowerShell中,如何检查一个字符串是否为null或空字符串?

603

在PowerShell中,是否有内置的类似于IsNullOrEmpty的函数来检查字符串是否为null或为空?

我目前还没有找到相关函数,如果有内置方法,我就不想自己写一个函数了。


3
希望这可以帮助:http://rkeithhill.wordpress.com/2007/01/06/checking-for-a-null-or-empty-string/ - gofor.net
13
你正在使用.NET,所以你不能调用String.IsNullOrEmpty吗? - Jon Skeet
16个回答

848

你们让这个问题变得太复杂了。PowerShell 可以优雅地处理它,例如:

> $str1 = $null
> if ($str1) { 'not empty' } else { 'empty' }
empty

> $str2 = ''
> if ($str2) { 'not empty' } else { 'empty' }
empty

> $str3 = ' '
> if ($str3) { 'not empty' } else { 'empty' }
not empty

> $str4 = 'asdf'
> if ($str4) { 'not empty' } else { 'empty' }
not empty

> if ($str1 -and $str2) { 'neither empty' } else { 'one or both empty' }
one or both empty

> if ($str3 -and $str4) { 'neither empty' } else { 'one or both empty' }
neither empty

41
是的,这就是我所说的,上面的示例展示了它的作用。但测试不会检查IsNullOrWhitespace()。 - Keith Hill
7
请看我上面的第一条评论,我建议在这种情况下使用IsNullOrWhitespace()。但是在使用PowerShell脚本11年后,我发现几乎不需要进行字符串测试。 :-) - Keith Hill
3
这是在 PowershellJavascript 中都存在的危险做法,如果变量类型没有受到限制。考虑以下代码: $str1=$false 或者 $str1=@(0) - dmitry
6
KeithHill. 对不起,这仍然是不安全的,因为你的意图不清楚。当你使用 [string]::IsNullOrEmpty 时,你是绝对清楚的。在我看来,PowerShell 是一个最奇怪的创造——大多数时候它过分丰富,但仍然缺少必要的东西。-isNullOrEmpty 谓词就是其中之一... - dmitry
2
@dmitry 理解了你想要的东西。通常,“真值”或“假值”就足够了,在有限的上下文中,你可以忽略很多其他事情。一个字符串数组可能会有0,但如果它不应该有,那么这不一定是_你的方法_需要关心的。(但也可能潜在的错误足够严重,值得额外的防御。) - John Neuhaus
显示剩余5条评论

681

您可以使用IsNullOrEmpty静态方法:

[string]::IsNullOrEmpty(...)

11
我更喜欢这种方式,因为无论你是否了解PowerShell,它都很明显它所做的事情-这对于非PowerShell程序员也是有意义的。 - pencilCake
31
我猜你可以直接使用 !$var。 - Shay Levy
6
需要注意的一点是,使用PowerShell时,如果将空字符串传递给命令或函数,它们不会保持为空值状态,而是会被转换为空字符串。请参考Microsoft Connect中的错误信息 https://connect.microsoft.com/PowerShell/feedback/details/861093/nullstring-value-is-not-preserved-when-passed-to-functions。 - JamieSee
53
考虑使用[String]::IsNullOrWhiteSpace(...)来验证空格是否为空。 - Sai
4
小心使用 ! 符号。它只适用于较新版本的 PowerShell。 !-not 的别名。 - Kellen Stuart

60

除了使用[string]::IsNullOrEmpty来检查空或空字符串之外,您还可以将字符串显式地转换为布尔值,或在布尔表达式中使用:

$string = $null
[bool]$string
if (!$string) { "string is null or empty" }

$string = ''
[bool]$string
if (!$string) { "string is null or empty" }

$string = 'something'
[bool]$string
if ($string) { "string is not null or empty" }

输出:

False
string is null or empty

False
string is null or empty

True
string is not null or empty

6
不错的观点。If子句在内部将括号内的所有内容转换为单个布尔值,这意味着if($string){对于非空且非null的情况要执行的操作}if(!$string){对于空或null的情况要执行的操作},无需显式转换[bool]即可。 - Ch.Idea
1
这些隐式转换是最危险的事情。你需要确保你有准确的字符串类型。考虑$string=@(0) - 这种情况很可能发生... - dmitry

27
若参数在函数中,你可以使用ValidateNotNullOrEmpty对其进行验证,以下是一个例子:

若参数在函数中,你可以使用ValidateNotNullOrEmpty对其进行验证,以下是一个例子:

Function Test-Something
{
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$UserName
    )

    #stuff todo
}


26

就我个人而言,我不认为一个只包含空格($STR3)的内容是“非空”的。

当一个只包含空格的变量被传递给一个参数时,通常会出现错误,提示该参数的值可能不是“$null”,而不是说它可能是一个空格。有些删除命令可能会误删根目录而不是子目录,如果子目录名称是“空格”,这就是不接受许多情况下包含空格的字符串的原因。

我认为这是实现它的最佳方式:

$STR1 = $null
IF ([string]::IsNullOrWhitespace($STR1)){'empty'} else {'not empty'}

空的

$STR2 = ""
IF ([string]::IsNullOrWhitespace($STR2)){'empty'} else {'not empty'}

$STR3 = " "
IF ([string]::IsNullOrWhitespace($STR3)){'empty !! :-)'} else {'not Empty :-('}

空的!!:-)

$STR4 = "Nico"
IF ([string]::IsNullOrWhitespace($STR4)){'empty'} else {'not empty'}

非空


.Net提供了String::IsNullOrEmpty方法来满足您的需求。 - dmitry

14

PowerShell 2.0替代 [string]::IsNullOrWhiteSpace() 的方法是 string -notmatch "\S"

("\S" 表示任何非空白字符)

> $null  -notmatch "\S"
True
> "   "  -notmatch "\S"
True
> " x "  -notmatch "\S"
False

性能非常接近:

> Measure-Command {1..1000000 |% {[string]::IsNullOrWhiteSpace("   ")}}
TotalMilliseconds : 3641.2089

> Measure-Command {1..1000000 |% {"   " -notmatch "\S"}}
TotalMilliseconds : 4040.8453

14
在这里有许多好答案;让我提供一个带有 PowerShell-习惯性解决方案的实用总结:
给定一个可能包含 $null 或字符串(或任何标量)的变量 $str:
# Test for $null or '' (empty string).
# Equivalent of: [string]::IsNullOrEmpty($str)
$str -like ''

# Test for $null or '' or all-whitespace.
# Equivalent of: [string]::IsNullOrWhitespace($str)
$str -notmatch '\S'  

注意:如果$str可以是一个集合(数组),请使用底部的类型不可知解决方案。
使用仅字符串的-like运算符会隐式将LHS强制转换为字符串,由于[string] $null生成空字符串,因此'' -like ''$null -like ''都返回$true
类似地,基于regex-match / -notmatch运算符作为仅字符串运算符,将其LHS操作数强制转换为字符串,在此转换中,$null被视为''\S是一个正则表达式转义序列,用于匹配任何空白字符(它是\s的否定形式)。 -match / -notmatch默认执行子字符串匹配(并且始终只返回一个匹配项),因此如果\S匹配,则意味着至少存在一个非空白字符。

注意:

由于PowerShell的动态类型,您可能无法提前知道给定变量中存储的值的类型。

虽然上述技术对于$null[string]实例和其他不可枚举类型的工作是可预测的,但可枚举的值(除了字符串)可能会产生令人惊讶的结果,因为如果-like-notmatch的左侧是可枚举的(宽泛地说:集合),操作将应用于每个元素,而不是返回单个布尔值,而是返回匹配元素的子数组

在条件语句的上下文中,将数组强制转换为布尔值的方式有些反直觉;如果数组只有一个元素,则该元素本身被强制转换为布尔值;如果有两个或更多元素,则数组总是被强制转换为$true,而不考虑元素的值 - 请参阅this answer的底部部分。例如:

# -> 'why?', because @('', '') -like '' yields @('', ''), which
# - due to being a 2-element array - is $true
$var = @('', '')
if ($var -like '') { 'why?' }

如果你将一个非字符串可枚举的左手边(LHS)转换为[string],PowerShell会通过空格连接其(字符串化的)元素来进行字符串化。 当你调用[string]::IsNullOrEmpty()或[string]::IsNullOrWhiteSpace()时,也会隐式地发生这种情况,因为它们的参数是[string]类型的。
因此,上述操作的类型不可知等效方式 - 使用所描述的字符串化规则 - 如下:
# Test for $null or '' (empty string) or any stringified value being ''
# Equivalent of: [string]::IsNullOrEmpty($var)
[string] $var -eq ''

# Test for $null or '' or all-whitespace or any stringified value being ''
# Equivalent of: [string]::IsNullOrWhitespace($var)
([string] $var).Trim() -eq ''

8

我有一个PowerShell脚本需要在一台过于陈旧的计算机上运行,该计算机没有[String] :: IsNullOrWhiteSpace()函数,因此我编写了自己的函数。

function IsNullOrWhitespace($str)
{
    if ($str)
    {
        return ($str -replace " ","" -replace "`t","").Length -eq 0
    }
    else
    {
        return $TRUE
    }
}

你能不能使用.Trim()代替列出空格类型?这样就可以写成$str.Trim().Length -eq 0 - HackSlash
$str -notmatch '\S' 应该足够覆盖所有类型的空白符,而不仅仅是空格和制表符。 - mklement0

7
# cases
$x = null
$x = ''
$x = ' '

# test
if ($x -and $x.trim()) {'not empty'} else {'empty'}
or
if ([string]::IsNullOrWhiteSpace($x)) {'empty'} else {'not empty'}

3
解决了 @KeithHill's answer 中未涵盖 IsNullOrWhitespace 情况的问题,在 PowerShell 7.1 及更高版本中,我们可以使用 null-conditional member operator 优雅地检查字符串是否为 null 或空格,而无需自己首先检查该字符串不是 $null,同时避免使用 [string]::IsNullOrWhitespace(string)

Note: You can also do this with PowerShell 7.0 if you enable the PSNullConditionalOperators experimental feature:

Enable-ExperimentalFeature -Name PSNullConditionalOperators
使用 Keith 的答案中的示例 $str3 (为了清晰起见,假装三元运算符在7.0之后也不存在):
$str3 = ' '
if ( ${str3}?.Trim() ) {
  'not empty or whitespace'
} else {
  'empty or whitespace'
}
empty or whitespace

如果 $str3 是非空值,则仅调用 .Trim() 方法;否则返回 $null
需要记住的一件事是,问号?可以作为变量名的一部分。这就是为什么我们必须先消除变量名的歧义,然后再应用条件访问运算符,例如:${str3}
既然我之前提到了三元运算符,而且由于这个答案已经围绕着 PowerShell 7.1 及更高版本展开,你可以通过使用三元运算符简化上面的代码块,几乎完全删除样板文件中的 if/then/else 语句。
${str3}?.Trim() ? 'not empty or whitespace' : 'empty or whitespace'

三元运算符是基本条件语句的简化版if/then/else。在这里,我不想过多地涉及它的细微差别,但可以理解为“如果单独问号?左侧为真,则执行问号右侧的内容,否则执行冒号:后面的内容。”

您可以在PowerShell文档中了解更多关于三元运算符的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接