Нуль коалесцирующий в PowerShell



есть ли оператор слияния null в powershell?



Я хотел бы иметь возможность выполнять эти команды c# в powershell:



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

8 ответов:

нет необходимости в расширениях сообщества 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" }

или в зависимости от того, что $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

как вы можете видеть, очень простая функция может дать вам немного свободы синтаксиса.

обновление: один дополнительный вариант рассмотреть в миксе-это более общая функция является истинной:

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 имеет фактический оператор слияния null или, по крайней мере, оператор, способный к такому поведению. Этот оператор -ne:

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

# Output:
alpha

он немного более универсален, чем оператор коалесценции null, поскольку он создает массив всех ненулевых элементов:

$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#'S ?? оператор:

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

объяснение

это объяснение основано на предложении редактирования от анонимного пользователя. Спасибо, кто бы вы ни были!

исходя из порядка операций, это работает в следующем порядке:

  1. The , оператор создает массив значений для проверки.
  2. The -ne оператор отфильтровывает все элементы из массива, соответствующие указанному значению--в данном случае null. Этот результатом является массив ненулевых значений в том же порядке, что и массив, созданный на Шаге 1.
  3. [0] используется для выбора первого элемента отфильтрованный массив.

упрощение, что:

  1. создать массив возможных значений, в предпочтительном порядке
  2. исключить нулевые значения из массива
  3. берем первый элемент из результирующего массива

предостережения

в отличие от C#'S null коалесцирующий оператор, каждое возможное выражение будет вычислено, так как первым шагом является создание массива.

это только половина ответа на первую половину вопроса, поэтому ответ на четверть, если хотите, но есть гораздо более простая альтернатива оператору слияния null при условии, что значение по умолчанию, которое вы хотите использовать, на самом деле является значением по умолчанию для типа:

string s = myval ?? "";

можно записать в Powershell как:

([string]myval)

или

int d = myval ?? 0;

переводится в Powershell:

([int]myval)

Я нашел первый из них полезным при обработке xml элемент, который может не существовать и который, если он существует, может иметь нежелательные пробелы вокруг него:

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

приведение к строке защищает от элемента null и предотвращает любой риск Trim() сбой.

при установке Модуль Расширений Сообщества Powershell затем вы можете использовать:

?? это псевдоним для Invoke-NullCoalescing.

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

?: это псевдоним для Invoke-Ternary.

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

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

возвращает

3

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

часто я нахожу, что мне также нужно рассматривать пустую строку как null при использовании coalesce. Я закончил тем, что написал функцию для этого, которая использует Zenexerдля объединения по той простой нуль сливаются, а затем использовать Кит Хилл ' 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)

ближе всего я могу получить это: $s = $myval |?? "new value"

я реализовал оператор коалесценции null для вышеизложенного, как это:

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

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

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

The условный тернарный оператор может быть реализован аналогичным образом.

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

и используется как: $x = ($myval -eq $null) |?: "" $otherval

Comments

    Ничего не найдено.