¿Hay un operador coalescente nulo en powershell?
Me gustaría poder hacer estos comandos de c # en powershell:
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
fuente
¿Hay un operador coalescente nulo en powershell?
Me gustaría poder hacer estos comandos de c # en powershell:
var s = myval ?? "new value";
var x = myval == null ? "" : otherval;
Powershell 7 introduce la fusión de nulos nativos, la asignación condicional nula y los operadores ternarios en Powershell.
Coalescencia nula
$null ?? 100 # Result is 100
"Evaluated" ?? (Expensive-Operation "Not Evaluated") # Right side here is not evaluated
Asignación condicional nula
$x = $null
$x ??= 100 # $x is now 100
$x ??= 200 # $x remains 100
Operador ternario
$true ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"
No necesita las extensiones de la comunidad de Powershell, puede usar las declaraciones estándar de Powershell if como expresión:
variable = if (condition) { expr1 } else { expr2 }
Entonces, para los reemplazos para su primera expresión C # de:
var s = myval ?? "new value";
se convierte en uno de los siguientes (según la preferencia):
$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }
o dependiendo de lo que $ myval pueda contener, puede usar:
$s = if ($myval) { $myval } else { "new value" }
y la segunda expresión de C # se asigna de manera similar:
var x = myval == null ? "" : otherval;
se convierte en
$x = if ($myval -eq $null) { "" } else { $otherval }
Ahora, para ser justos, estos no son muy rápidos y no son tan cómodos de usar como los formularios de C #.
También puede considerar envolverlo en una función muy simple para hacer las cosas más legibles:
function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
$s = Coalesce $myval "new value"
o posiblemente 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 puede ver, una función muy simple puede brindarle bastante libertad de sintaxis.
ACTUALIZACIÓN: Una opción adicional a considerar en la mezcla es una función IsTrue más genérica:
function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
$x = IfTrue ($myval -eq $null) "" $otherval
Luego combina esa es la capacidad de Powershell para declarar alias que se parecen un poco a los operadores, terminas con:
New-Alias "??" Coalesce
$s = ?? $myval "new value"
New-Alias "?:" IfTrue
$ans = ?: ($q -eq "meaning of life") 42 $otherval
Claramente, esto no será del gusto de todos, pero puede ser lo que estás buscando.
Como señala Thomas, otra sutil diferencia entre la versión de C # y la anterior es que C # realiza un cortocircuito de los argumentos, pero las versiones de Powershell que involucran funciones / alias siempre evaluarán todos los argumentos. Si esto es un problema, use la if
forma de expresión.
The variable '$myval' cannot be retrieved because it has not been set.
.$myval = $null
antes de realizar la prueba, el error debería desaparecer.$null -ne $a
no se puede encontrar una referencia decente ahora, pero es una práctica de larga data.PowerShell 7 y posterior
PowerShell 7 presenta muchas características nuevas y migra de .NET Framework a .NET Core. A mediados de 2020, no ha reemplazado por completo las versiones heredadas de PowerShell debido a la dependencia de .NET Core, pero Microsoft ha indicado que tienen la intención de que la familia Core eventualmente reemplace a la familia Framework heredada. Para cuando lea esto, es posible que una versión compatible de PowerShell venga preinstalada en su sistema; de lo contrario, consulte https://github.com/powershell/powershell .
Según la documentación , los siguientes operadores son compatibles de forma inmediata en PowerShell 7.0:
??
??=
... ? ... : ...
Estos funcionan como cabría esperar para la fusión nula:
Dado que se introdujo un operador ternario, ahora es posible lo siguiente, aunque no es necesario dada la adición de un operador de fusión nulo:
A partir de 7.0, lo siguiente también está disponible si la
PSNullConditionalOperators
función opcional está habilitada , como se explica en los documentos ( 1 , 2 ):?.
?[]
Estos tienen algunas advertencias:
${}
si van seguidas de uno de los operadores experimentales porque se permiten signos de interrogación en los nombres de las variables. No está claro si este será el caso cuando las funciones pasen del estado experimental (consulte el número 11379 ). Por ejemplo,${x}?.Test()
usa el operador new, pero se$x?.Test()
ejecutaTest()
en una variable llamada$x?
.?(
operador como cabría esperar si viene de TypeScript. Lo siguiente no funcionará:$x.Test?()
PowerShell 6 y versiones anteriores
Las versiones de PowerShell anteriores a la 7 tienen un operador de fusión nulo real, o al menos un operador que es capaz de tal comportamiento. Ese operador es
-ne
:Es un poco más versátil que un operador de fusión nulo, ya que crea una matriz de todos los elementos no nulos:
-eq
funciona de manera similar, lo cual es útil para contar entradas nulas:Pero de todos modos, aquí hay un caso típico para reflejar el
??
operador de C # :Explicación
Esta explicación se basa en una sugerencia de edición de un usuario anónimo. ¡Gracias, quienquiera que seas!
Según el orden de las operaciones, esto funciona en el siguiente orden:
,
operador crea una matriz de valores para probar.-ne
operador filtra los elementos de la matriz que coinciden con el valor especificado, en este caso, nulo. El resultado es una matriz de valores no nulos en el mismo orden que la matriz creada en el Paso 1.[0]
se utiliza para seleccionar el primer elemento de la matriz filtrada.Simplificando eso:
Advertencias
A diferencia del operador de fusión nula de C #, se evaluarán todas las expresiones posibles, ya que el primer paso es crear una matriz.
fuente
function DidItRun($a) { Write-Host "It ran with $a"; return $a }
y corra((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
para ver esto.,
tiene una prioridad tan alta. Para cualquiera que esté confundido sobre cómo funciona esto,($null, 'alpha', 1 -ne $null)[0]
es lo mismo que(($null, 'alpha', 1) -ne $null)[0]
. De hecho, los únicos dos operadores de "guión" con mayor precendencia son-split
y-join
(y guión unario, es decir,-4
o-'56'
).Esta es solo la mitad de una respuesta a la primera mitad de la pregunta, por lo que un cuarto de respuesta si lo desea, pero hay una alternativa mucho más simple al operador de fusión nula siempre que el valor predeterminado que desea usar sea en realidad el valor predeterminado para el tipo :
Puede escribirse en Powershell como:
O
se traduce en Powershell:
Encontré el primero de estos útil al procesar un elemento xml que podría no existir y que, si existiera, podría tener espacios en blanco no deseados alrededor:
La conversión a cadena protege contra el elemento nulo y evita cualquier riesgo de
Trim()
falla.fuente
([string]$null)
->""
parece un "efecto secundario útil, pero desafortunado" :($null, $null, 3 | Select -First 1
devoluciones
3
fuente
Si instala el módulo de extensiones de la comunidad de Powershell , puede usar:
?? es el alias de Invoke-NullCoalescing.
?: es el alias de Invoke-Ternary.
fuente
¡Finalmente, PowerShell 7 obtuvo operadores de asignación de coalescencia nula !
fuente
fuente
fuente
A menudo encuentro que también necesito tratar la cadena vacía como nula cuando uso coalesce. Terminé escribiendo una función para esto, que usa la solución de Zenexer para fusionar para la fusión nula simple, y luego usé la de Keith Hill para verificar nulos o vacíos, y lo agregué como una bandera para que mi función pudiera hacer ambas cosas.
Una de las ventajas de esta función es que también maneja tener todos los elementos nulos (o vacíos), sin lanzar una excepción. También se puede usar para muchas variables de entrada arbitrarias, gracias a cómo PowerShell maneja las entradas de la matriz.
Esto produce los siguientes resultados de la prueba:
Código de prueba:
fuente
Lo más cerca que puedo conseguir es:
$Val = $MyVal |?? "Default Value"
Implementé el operador de fusión nula para lo anterior de esta manera:
El operador ternario condicional podría implementarse de manera similar.
Y usado como:
$Val = $MyVal |?: $MyVal "Default Value"
fuente