【问题标题】:PowerShell syntax for something like :? operator? [duplicate]类似 :? 的 PowerShell 语法操作员? [复制]
【发布时间】:2019-03-24 18:53:58
【问题描述】:

我正在做一件事情,我挑选出一个 XML 文档并将一些元素的文本内容写入一个文件。加载 XML 文档后,基本方法非常简单:我所做的只是

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

但我需要安排在叶子元素没有内容或根本不存在的情况下发出一个空行。

我可以把内容赋值给一个变量,测试这个变量是否为空,如果是空字符串,然后写到文件中,

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

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

【问题讨论】:

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


    【解决方案1】:

    更新

    • PowerShell(核心)7.0引入了ternary operator$condition ? $valueIfTrue : $valueIfFalse)和null-coalescing operators$possibleNullValue ?? $valueIfNull$possibleNullValue ??= $valueIfNull}

    • PowerShell(核心)7.1 引入了null-conditional operators${possibleNullValue}?.Property${possibleNullValue}?[0]

      • 请注意 - 不幸的是需要在变量名周围使用 {...},因为 - 违反直觉 - ? 当前是合法的变量名字符 - 请参阅 GitHub issue #14025

    此答案的其余部分显示模拟PowerShell 6.x 及更早版本的三元运算符和空值合并的方法


    不幸的是,PowerShell没有ternary [conditional] operator(例如,
    $condition ? $valueIfTrue : $valueIfFalse)或null-coalescing operator(例如,
    $possibleNullValue ?? $valueIfNull) strong> 从 PowerShell Core 6.1.0 开始。

    但是,增强语言以支持这些 is being proposed
    如果您希望看到这种情况发生,请在那里发出您的声音 - 即使是简单的“竖起大拇指”也会有所帮助。

    在您的具体情况下,您正在寻找 null-coalescing 运算符,并且有 - 次优 - 解决方法: p>


    定义一个自定义函数,如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 中以不同的方式放置它们,因为实现是函数(例如,
      C# 中的a ?? b 与 PowerShell 中的?? $a $b)。


    使用具有隐式布尔到整数转换的辅助数组

    $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 上的,因为在 RHS 上,如果 $foo 恰好是 array 值,它将执行不同的测试。
    • 数组索引的上下文中,[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]

    【讨论】:

      【解决方案2】:

      这是我的目标是添加一个小 cmdlet。 PowerShell Inline If (IIf)

      $foo = $null;
      Write-Host (IIf $foo "True" "False")
      
      Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}}
      

      【讨论】:

        【解决方案3】:

        赋值可以作为表达式进行计算。这对您来说意味着如果您只关心简洁而不是可读性,那么您可以改变您已经完成的工作:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-18
          • 2011-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多