PowerShell语法:操作员?

时间:2018-10-19 21:00:09

标签: powershell ternary-operator null-coalescing-operator

我正在做的事情是我将XML文档拆开并将一些元素的文本内容写到文件中。加载XML文档后,基本方法很简单:我要做的只是

$DI_XMLResponse.result.gudid.device.versionModelNumber | Out-File -FilePath $OutputFile -Append -NoClobber -Encoding ascii

但是,如果leaf元素不存在或根本不存在,我需要安排一个空白行。

我可以将内容分配给变量,测试变量是否为null,如果是,则将其设为空字符串,然后将其写出到文件中,

$foo = $DI_XMLResponse.result.gudid.device.versionModelNumber if (!$foo) $foo = '' $foo | Out-File -FilePath $OutputFile -Append -NoClobber -Encoding ascii

但是我希望找到一些更紧凑的表达方式。有一个吗?

3 个答案:

答案 0 :(得分:5)

不幸的是, PowerShell没 没有ternary [conditional] operator(例如,
condition ? if-true-value : else-valuenull-coalescing operator(例如,
 possiblyNullValue ?? valueIfNull
(自PowerShell Core 6.1.0起)。

但是,请增强语言以支持这些is being proposed
如果您希望看到这种情况发生,请在此听到您的声音-甚至是简单的“竖起大拇指”的帮助。

在您的特定情况下,您正在寻找 null-coalescing 操作符,并且-次优-解决方法


定义自定义函数,如Ryan Schlueter's answer所示,用于三元运算符。

对于 null-coalescing 运算符,它可能类似于:

function ?? ($PossiblyNull, $ValueIfNull) { 
  if ($null -eq $PossiblyNull) { $ValueIfNull } else { $PossiblyNull }
}

应用于您的代码:

?? $DI_XMLResponse.result.gudid.device.versionModelNumber '' |
  Out-File -FilePath $OutputFile -Append -NoClobber -Encoding ascii 

自定义功能的缺点是:

  • 您需要将其包含或导入到要使用它们的每段代码中。

  • 如果您选择熟悉的名称,例如?:??,则操作数的位置会引起混淆,因为您必须(始终)将它们不同地放置在PowerShell,以实现为 function (例如,
    C#中的a ?? b与PowerShell中的?? $a $b)。


使用 helper数组进行隐式布尔到整数转换

$foo = $DI_XMLResponse.result.gudid.device.versionModelNumber
($foo, '')[$null -eq $foo] | Out-File -FilePath $OutputFile -Append -NoClobber -Encoding ascii
  • ($foo, '')是一个包含两个可能输出的值的数组。
  • $null -eq $foo是有条件的,如果$False$foo,则求和为$null,否则为$False
    • 请注意,$null是有意放置在LHS上的,因为如果$foo恰好是 array 值,在RHS上它将执行不同的测试。
  • 数组索引的上下文中,期望使用[int]值,因此$True会自动转换为1,而$False结果在0中。
  • 最终结果是,如果$foo$null,则输出'';否则,将按原样使用$foo

此方法的缺点

  • 未应用短路逻辑;也就是说,在选择适当的元素之前,将无条件地对这两个数组元素进行评估

  • 如果只需要 null-coalescing ,则必须先存储值以测试$null在变量中;例如模仿
    (Get-Foo Bar) ?? '(none)'
    您必须首先将Get-Foo Bar的输出保存在辅助变量中,以便您可以编写:
    $aux = Get-Foo Bar; ($aux, '(none)')[$null -eq $aux]

答案 1 :(得分:1)

这是我要添加的小cmdlet。 PowerShell Inline If (IIf)

$foo = $null;
Write-Host (IIf $foo "True" "False")

Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}}

答案 2 :(得分:1)

赋值可以作为表达式求值。这对您意味着什么,如果您只关心简洁而不是可读性,则可以改变您所做的事情:

if (-not ($foo = $xml. ...)) {
    $foo = ''
}