Existe um operador de coalescência nulo no PowerShell?
Eu gostaria de poder fazer estes comandos c # no PowerShell:
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
Existe um operador de coalescência nulo no PowerShell?
Eu gostaria de poder fazer estes comandos c # no PowerShell:
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
O Powershell 7 apresenta coalescência nula nativa, atribuição condicional nula e operadores ternários no Powershell.
Null Coalescing
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Atribuição Condicional Nula
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Operador Ternário
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
Não há necessidade de extensões da comunidade Powershell, você pode usar as instruções if padrão do Powershell como uma expressão:
variable = if (condition) { expr1 } else { expr2 }
Então, para as substituições de sua primeira expressão C # de:
var s = myval ?? "new value";
torna-se um dos seguintes (dependendo da preferência):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
ou dependendo do que $ myval possa conter, você pode usar:
$s = if ($myval) { $myval } else { "new value" }
e a segunda expressão C # mapeia de maneira semelhante:
var x = myval == null ? "" : otherval;
torna-se
$x = if ($myval -eq $null) { "" } else { $otherval }
Agora, para ser justo, eles não são muito rápidos e nem de longe tão confortáveis de usar quanto os formulários C #.
Você também pode considerar envolvê-lo em uma função muito simples para tornar as coisas mais legíveis:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
ou possivelmente como, IfNull:
function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval
Como você pode ver, uma função muito simples pode fornecer um pouco de liberdade de sintaxe.
ATUALIZAÇÃO: uma opção extra a ser considerada na combinação é uma função IsTrue mais genérica:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Em seguida, combine isso é a capacidade do Powershell de declarar aliases que se parecem um pouco com operadores, você acaba com:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
É claro que isso não vai agradar a todos, mas pode ser o que você está procurando.
Como observa Thomas, uma outra diferença sutil entre a versão C # e a anterior é que o C # causa um curto-circuito nos argumentos, mas as versões do Powershell envolvendo funções / aliases sempre avaliarão todos os argumentos. Se isso for um problema, use a if
forma de expressão.
The variable '$myval' cannot be retrieved because it has not been set.
.$myval = $null
antes de fazer o teste, o erro deve desaparecer.$null -ne $a
Não é possível encontrar uma referência decente agora, mas é uma prática de longa data.PowerShell 7 e posterior
O PowerShell 7 apresenta muitos novos recursos e migra do .NET Framework para o .NET Core. Em meados de 2020, ele não substituiu completamente as versões legadas do PowerShell devido à dependência do .NET Core, mas a Microsoft indicou que pretende que a família Core eventualmente substitua a família Framework legada. No momento em que você lê isto, uma versão compatível do PowerShell pode vir pré-instalada em seu sistema; caso contrário, consulte https://github.com/powershell/powershell .
De acordo com a documentação , os seguintes operadores têm suporte imediato no PowerShell 7.0:
??
??=
... ? ... : ...
Funcionam como você esperaria para coalescência nula:
Uma vez que um operador ternário foi introduzido, o seguinte agora é possível, embora seja desnecessário devido à adição de um operador coalescente nulo:
A partir da versão 7.0, os itens a seguir também estarão disponíveis se o
PSNullConditionalOperators
recurso opcional estiver ativado , conforme explicado nos documentos ( 1 , 2 ):?.
?[]
Estes têm algumas ressalvas:
${}
se seguidas por um dos operadores experimentais porque pontos de interrogação são permitidos em nomes de variáveis. Não está claro se este será o caso se / quando os recursos passarem do status experimental (consulte a edição nº 11379 ). Por exemplo,${x}?.Test()
usa o novo operador, mas$x?.Test()
é executadoTest()
em uma variável chamada$x?
.?(
operador como você poderia esperar se você estiver vindo do TypeScript. O seguinte não funcionará:$x.Test?()
PowerShell 6 e anterior
As versões do PowerShell anteriores a 7 têm um operador real de coalescência nula ou, pelo menos, um operador capaz de tal comportamento. Esse operador é
-ne
:É um pouco mais versátil do que um operador de coalescência nulo, pois cria uma matriz de todos os itens não nulos:
-eq
funciona de forma semelhante, o que é útil para contar entradas nulas:Mas, de qualquer forma, aqui está um caso típico para espelhar o
??
operador C # :Explicação
Esta explicação é baseada em uma sugestão de edição de um usuário anônimo. Obrigado, seja você quem for!
Com base na ordem das operações, funciona na seguinte ordem:
,
operador cria uma matriz de valores a serem testados.-ne
operador filtra todos os itens da matriz que correspondem ao valor especificado - neste caso, nulo. O resultado é uma matriz de valores não nulos na mesma ordem da matriz criada na Etapa 1.[0]
é usado para selecionar o primeiro elemento da matriz filtrada.Simplificando isso:
Ressalvas
Ao contrário do operador de coalescência nula do C #, todas as expressões possíveis serão avaliadas, pois a primeira etapa é criar uma matriz.
fonte
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
e corra((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
para ver isso.,
tem uma precedência muito alta. Para quem está confuso sobre como isso funciona,($null, 'alpha', 1 -ne $null)[0]
é o mesmo que(($null, 'alpha', 1) -ne $null)[0]
. Na verdade, os únicos dois operadores de "traço" com maior precedência são-split
e-join
(e traço unário?-4
Ou seja, ou-'56'
).Esta é apenas meia resposta para a primeira metade da pergunta, portanto, um quarto de resposta se quiser, mas há uma alternativa muito mais simples para o operador de coalescência nula, desde que o valor padrão que você deseja usar seja na verdade o valor padrão para o tipo :
Pode ser escrito no Powershell como:
Ou
se traduz em PowerShell:
Achei a primeira delas útil ao processar um elemento xml que pode não existir e que, se existisse, poderia ter um espaço em branco indesejado ao redor:
A conversão em string protege contra o elemento nulo e evita qualquer risco de
Trim()
falha.fonte
([string]$null)
->""
parece ser um "efeito colateral útil, mas infeliz" :($null, $null, 3 | Select -First 1
retorna
3
fonte
Se você instalar o Powershell Community Extensions Module , poderá usar:
?? é o alias de Invoke-NullCoalescing.
?: é o alias de Invoke-Ternary.
fonte
Finalmente, o PowerShell 7 tem operadores de atribuição Null Coalescing !
fonte
fonte
fonte
Freqüentemente, acho que também preciso tratar string vazia como nula ao usar coalescer. Acabei escrevendo uma função para isso, que usa a solução de Zenexer para coalescer para a coalescência nula simples e, em seguida, usei a de Keith Hill para verificação de nulo ou vazio e adicionei isso como um sinalizador para que minha função pudesse fazer as duas coisas.
Uma das vantagens dessa função é que ela também lida com ter todos os elementos nulos (ou vazios), sem lançar uma exceção. Ele também pode ser usado para muitas variáveis de entrada arbitrárias, graças à forma como o PowerShell lida com entradas de array.
Isso produz os seguintes resultados de teste:
Código de teste:
fonte
O mais próximo que posso chegar é:
$Val = $MyVal |?? "Default Value"
Implementei o operador de coalescência nulo para o acima assim:
O operador ternário condicional pode ser implementado de maneira semelhante.
E usado como:
$Val = $MyVal |?: $MyVal "Default Value"
fonte