在PowerShell中无效合并

在PowerShell中是否有一个空合并运算符?

我想能够在PowerShell中执行这些C#命令:

var s = myval ?? "new value"; var x = myval == null ? "" : otherval; 

不需要Powershell社区扩展,您可以使用标准Powershell if语句作为expression式:

 variable = if (condition) { expr1 } else { expr2 } 

所以要replace你的第一个expression式是:

 var s = myval ?? "new value"; 

成为下列之一(取决于偏好):

 $s = if ($myval -eq $null) { "new value" } else { $myval } $s = if ($myval -ne $null) { $myval } else { "new value" } 

或者取决于$ myval可能包含的内容,你可以使用:

 $s = if ($myval) { $myval } else { "new value" } 

第二个expression式以类似的方式映射:

 var x = myval == null ? "" : otherval; 

 $x = if ($myval -eq $null) { "" } else { $otherval } 

现在公平的说,这些都不是很活泼,也不像C#表单那么舒服。

你也可以考虑把它封装在一个非常简单的函数中,使其更具可读性:

 function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } } $s = Coalesce $myval "new value" 

或者可能是,IfNull:

 function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } } $s = IfNull $myval "new value" $myval $x = IfNull $myval "" $otherval 

正如你所看到的,一个非常简单的函数可以给你相当多的语法自由。

更新:在混合中需要考虑的另外一个选项是更通用的IsTrue函数:

 function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } } $x = IfTrue ($myval -eq $null) "" $otherval 

然后结合Powershell的能力来声明看起来有点像运营商的别名,你最终:

 New-Alias "??" Coalesce $s = ?? $myval "new value" New-Alias "?:" IfTrue $ans = ?: ($q -eq "meaning of life") 42 $otherval 

显然这不是每个人的口味,但可能是你在找什么。

是的,PowerShell确实有一个实际的空合并运算符,或者至less有一个能够这样的行为的运算符。 该运算符是-ne

 # Format: # ($a, $b, $c -ne $null)[0] ($null, 'alpha', 1 -ne $null)[0] # Output: alpha 

它比空的合并运算符更通用一些,因为它使所有非空项目的数组:

 $items = $null, 'alpha', 5, 0, '', @(), $null, $true, $false $instances = $items -ne $null [string]::Join(', ', ($instances | ForEach-Object -Process { $_.GetType() })) # Result: System.String, System.Int32, System.Int32, System.String, System.Object[], System.Boolean, System.Boolean 

-eq工作原理类似,这对计算空条目非常有用:

 ($null, 'a', $null -eq $null).Length # Result: 2 

但无论如何,这是一个典型的例子来镜像C#的?? 运营商:

 'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output 

说明

这个解释是基于来自匿名用户的编辑build议。 谢谢,不pipe你是谁!

根据操作顺序,按以下顺序运行:

  1. 该运算符创build一个值的数组进行testing。
  2. -ne运算符从数组中过滤出与指定值相匹配的任何项 – 在本例中为null。 结果是以与步骤1中创build的数组相同的顺序的非空值数组。
  3. [0]select过滤数组的第一个元素。

简化:

  1. 按照首选顺序创build一个可能值的数组
  2. 排除数组中的所有空值
  3. 从结果数组中获取第一项

注意事项

与C#的空合并运算符不同,每个可能的expression式都将被计算,因为第一步是创build一个数组。

这只是问题前半部分的一半答案,所以四分之一的答案,如果你愿意,但有一个简单的替代空合并运算符提供的默认值,你想要使用的实际上是默认值的types:

 string s = myval ?? ""; 

可以写成Powershell:

 ([string]myval) 

要么

 int d = myval ?? 0; 

转换为Powershell:

 ([int]myval) 

当处理一个可能不存在的xml元素时,我发现这些元素中的第一个元素很有用,如果它确实存在的话,可能会有不需要的空白。

 $name = ([string]$row.td[0]).Trim() 

转换为string可防止元素为空,并防止任何Trim()失败的风险。

如果您安装了Powershell社区扩展模块,那么您可以使用:

?? 是Invoke-NullCoalescing的别名。

 $s = ?? {$myval} {"New Value"} 

?:是Invoke-Ternary的别名。

 $x = ?: {$myval -eq $null} {""} {$otherval} 
 function coalesce { Param ([string[]]$list) #$default = $list[-1] $coalesced = ($list -ne $null) $coalesced[0] } function coalesce_empty { #COALESCE for empty_strings Param ([string[]]$list) #$default = $list[-1] $coalesced = (($list -ne $null) -ne '')[0] $coalesced[0] } 

通常我发现在使用coalesce时,我也需要将空string视为null。 我最终为此写了一个函数,它使用Zenexer的解决scheme来合并简单的null合并,然后使用Keith Hill的空或空检查,并将其作为标记添加,所以我的函数可以同时执行这两个操作。

这个函数的优点之一是,它也处理所有元素为null(或空),而不会引发exception。 它也可以用于任意多个inputvariables,这要感谢PowerShell如何处理数组input。

 function Coalesce([string[]] $StringsToLookThrough, [switch]$EmptyStringAsNull) { if ($EmptyStringAsNull.IsPresent) { return ($StringsToLookThrough | Where-Object { $_ } | Select-Object -first 1) } else { return (($StringsToLookThrough -ne $null) | Select-Object -first 1) } } 

这会产生以下testing结果:

 Null coallesce tests: 1 (w/o flag) - empty/null/'end' : 1 (with flag) - empty/null/'end' : end 2 (w/o flag) - empty/null : 2 (with flag) - empty/null : 3 (w/o flag) - empty/null/$false/'end' : 3 (with flag) - empty/null/$false/'end' : False 4 (w/o flag) - empty/null/"$false"/'end' : 4 (with flag) - empty/null/"$false"/'end' : False 5 (w/o flag) - empty/'false'/null/"$false"/'end': 5 (with flag) - empty/'false'/null/"$false"/'end': false 

testing代码:

 Write-Host "Null coalesce tests:" Write-Host "1 (w/o flag) - empty/null/'end' :" (Coalesce '', $null, 'end') Write-Host "1 (with flag) - empty/null/'end' :" (Coalesce '', $null, 'end' -EmptyStringAsNull) Write-Host "2 (w/o flag) - empty/null :" (Coalesce('', $null)) Write-Host "2 (with flag) - empty/null :" (Coalesce('', $null) -EmptyStringAsNull) Write-Host "3 (w/o flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end') Write-Host "3 (with flag) - empty/null/`$false/'end' :" (Coalesce '', $null, $false, 'end' -EmptyStringAsNull) Write-Host "4 (w/o flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end') Write-Host "4 (with flag) - empty/null/`"`$false`"/'end' :" (Coalesce '', $null, "$false", 'end' -EmptyStringAsNull) Write-Host "5 (w/o flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end') Write-Host "5 (with flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end' -EmptyStringAsNull) 

$null, $null, 3 | Select -First 1

回报

3