在powershell中无法合并

时间:2012-05-16 17:49:16

标签: powershell null-coalescing-operator

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

我希望能够在powershell中执行这些c#命令:

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

10 个答案:

答案 0 :(得分:103)

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

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

所以对你的第一个表达式的替换是:

var s = myval ?? "new value";

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

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

或取决于my myval可能包含的内容:

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

并且第二个表达式以类似的方式映射:

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

显然,这不符合每个人的口味,但可能正是您所寻找的。

答案 1 :(得分:80)

是的,PowerShell确实有一个实际的空合并运算符,或者至少是一个能够执行此类行为的运算符。该运算符为-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

解释

此解释基于匿名用户的编辑建议。谢谢,无论你是谁!

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

  1. ,运算符创建要测试的值数组。
  2. -ne运算符过滤掉数组中与指定值匹配的所有项 - 在本例中为null。结果是一个非空值数组,其顺序与步骤1中创建的数组相同。
  3. [0]用于选择已过滤数组的第一个元素。
  4. 简化:

    1. 按首选顺序创建可能值的数组
    2. 排除数组中的所有空值
    3. 从结果数组中取出第一项
    4. 注意事项

      与C#的空合并运算符不同,将评估每个可能的表达式,因为第一步是创建数组。

答案 2 :(得分:13)

这只是问题前半部分的答案的一半,所以如果你愿意,四分之一的答案,但是如果你想要使用的默认值实际上是默认值,那么有一个更简单的替代空合并运算符的方法。对于类型:

string s = myval ?? "";

可以用Powershell写成:

([string]myval)

或者

int d = myval ?? 0;

转换为Powershell:

([int]myval)

我在处理可能不存在的xml元素时发现第一个有用,如果它确实存在,可能会有不需要的空格:

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

强制转换为字符串可以防止元素为空,并防止Trim()失败的风险。

答案 3 :(得分:9)

如果您安装Powershell Community Extensions Module,则可以使用:

??是Invoke-NullCoalescing的别名。

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

?:是Invoke-Ternary的别名。

$x = ?: {$myval -eq $null} {""} {$otherval}

答案 4 :(得分:9)

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

返回

3

答案 5 :(得分:3)

@($null,$null,"val1","val2",5) | select -First 1

答案 6 :(得分:2)

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]
 }

答案 7 :(得分:2)

通常我发现在使用coalesce时我还需要将空字符串视为null。我最后为此编写了一个函数,它使用Zenexer的解决方案来合并简单的空合并,然后使用Keith Hill' s进行空或空检查,以及补充说,作为一个标志,所以我的功能可以做到这两点。

此函数的一个优点是,它还可以处理所有元素为null(或为空),而不会抛出异常。由于PowerShell处理数组输入的方式,它也可以用于任意多个输入变量。

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)
  }  
}

这会产生以下测试结果:

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

测试代码:

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)

答案 8 :(得分:2)

最后,PowerShell 7得到了Null Coalescing assignment operators

PS > $null ?? "a"
a
PS > "x" ?? "y"
x
PS > $x = $null
PS > $x ??= "abc"
PS > $x
abc
PS > $x ??= "xyz"
PS > $x
abc

答案 9 :(得分:0)

我能得到的最接近的是:$Val = $MyVal |?? "Default Value"

我为上述代码实现了null coalescing operator

function NullCoalesc {
    param (
        [Parameter(ValueFromPipeline=$true)]$Value,
        [Parameter(Position=0)]$Default
    )

    if ($Value) { $Value } else { $Default }
}

Set-Alias -Name "??" -Value NullCoalesc

conditional ternary operator可以以类似的方式实现。

function ConditionalTernary {
    param (
        [Parameter(ValueFromPipeline=$true)]$Value,
        [Parameter(Position=0)]$First,
        [Parameter(Position=1)]$Second
    )

    if ($Value) { $First } else { $Second }
}

Set-Alias -Name "?:" -Value ConditionalTernary

其用法类似于:$Val = $MyVal |?: $MyVal "Default Value"