- 05/23/2020
- 18 minutos para leer
-
- j
- x
- t
- D
- s
al Igual que muchos otros idiomas, PowerShell tiene instrucciones para condicionalmente la ejecución de código en yourscripts. Una de esas declaraciones es la declaración If., Hoy vamos a profundizar en uno de los comandos más fundamentales de PowerShell.
Nota
La versión original de este artículo apareció en el blog escrito por @KevinMarquette. El equipo de PowerShell agradece a Kevin por compartir este contenido con nosotros. Por favor, echa un vistazo a su blog atPowerShellExplained.com.
ejecución condicional
sus scripts a menudo necesitan tomar decisiones y realizar diferentes lógicas basadas en esas decisiones.Esto es lo que quiero decir con ejecución condicional., Tiene una declaración o valor para evaluar, luego ejecuta una sección diferente de código basada en esa evaluación. Esto es exactamente lo que hace la instrucción if
.
La instrucción if
Aquí hay un ejemplo básico de la etiqueta if
instrucción:
$condition = $trueif ( $condition ){ Write-Output "The condition was true"}
La primera cosa que el if
declaración que hace es evaluar la expresión en paréntesis. Si evalúa $true
, entonces ejecuta el scriptblock
en las llaves., Si el valor era $false
, entonces saltaría ese bloque de scripts.
en el ejemplo anterior, la instrucción if
estaba evaluando la variable $condition
. Era de$true
y habría ejecutado el Write-Output
comando dentro del bloque script.
en algunos idiomas, puede colocar una sola línea de código después de la instrucción if
y se ejecuta. Ese no es el caso en PowerShell. Debe proporcionar un scriptblock
completo con Llaves para que funcione correctamente.,
operadores de comparación
el uso más común de la instrucción if
es comparar dos elementos entre sí. PowerShell tiene operadores especiales para diferentes escenarios de comparación. Cuando se utiliza un operador de comparación, el valor en el lado izquierdo se compara con el valor en el lado derecho.
-eq para Igualdad
el -eq
hace una comprobación de igualdad entre dos valores para asegurarse de que son iguales entre sí.,
$value = Get-MysteryValueif ( 5 -eq $value ){ # do something}
en este ejemplo, Estoy tomando un valor conocido de 5
y comparándolo con mi $value
para ver si coinciden.
un posible caso de uso es comprobar el estado de un valor antes de realizar una acción sobre él. Puede obtener un servicio y comprobar que el estado se estaba ejecutando antes de llamar a Restart-Service
en él.
es común en otros lenguajes como C# usar ==
para la igualdad (por ejemplo: 5 == $value
) pero eso no funciona con PowerShell., Otro error común que la gente comete es usar el signo igual (por ejemplo:5 = $value
) que está reservado para asignar valores a variables. Al poner su valor conocido en la izquierda, hace que ese error sea más incómodo de cometer.
este operador (y otros) tiene algunas variaciones.,
-
-eq
igualdad insensible a mayúsculas y minúsculas -
-ieq
igualdad insensible a mayúsculas y minúsculas -
-ceq
igualdad h3>muchos operadores tienen un operador relacionado que está comprobando el resultado opuesto.
-ne
verifica que los valores no sean iguales entre sí.if ( 5 -ne $value ){ # do something}
Use esto para asegurarse de que la acción solo se ejecute si el valor no es
5
., Un buen uso-casos donde sería comprobar si un servicio estaba en el estado de ejecución antes de intentar iniciarlo.variaciones:
-
-ne
case-insensitive not equal -
-ine
case-insensitive not equal -
-cne
case-sensitive not equal
estas son variaciones inversas de
-eq
. Voy a agrupar estos tipos juntos cuando lista variationsfor otros operadores.,-gt -ge -lt -le de mayor que o menor que
Estos operadores se utilizan cuando comprueba si un valor es mayor o menor que otro valor.El
-gt -ge -lt -le
significa GreaterThan, GreaterThanOrEqual, LessThan y LessThanOrEqual.,eater than or equal, case-insensitive -
-
-cge
greater than or equal, case-sensitive -
-lt
less than -
-ilt
less than, case-insensitive -
-clt
menos que, sensible a mayúsculas y minúsculas -
-le
menos o igual -
-ile
menos o igual, insensible a mayúsculas y minúsculas -
-cle
menor o igual, distingue entre mayúsculas y minúsculas
no se por qué usaría las opciones que distinguen entre mayúsculas y minúsculas y las que no las distinguen para estos operadores.,
-como coincidencias de comodines
PowerShell tiene su propia sintaxis de coincidencia de patrones basada en comodines y puede usarla con el operador -like
. Estos patrones comodín son bastante básicos.
-
?
coincide con cualquier carácter individual -
*
coincide con cualquier número de caracteres
$value = 'S-ATX-SQL01'if ( $value -like 'S-*-SQL??'){ # do something}
Es importante señalar que el patrón coincide con la cadena entera. Si necesita hacer coincidir algo en el medio de la cadena, debe colocar el *
en ambos extremos de la cadena.,e»>
variaciones:
-
-like
comodín insensible a mayúsculas y minúsculas -
-ilike
comodín insensible a mayúsculas y minúsculas -
-clike
comodín> -
-notlike
comodín insensible a mayúsculas y minúsculas no coincidente -
-inotlike
comodín insensible a mayúsculas y minúsculas no coincidente -
-cnotlike
comodín/h3>el operador
-match
le permite comprobar si una cadena tiene una coincidencia basada en expresiones regulares., Utilice thiswhen los patrones de comodín no son lo suficientemente flexibles para usted.$value = 'S-ATX-SQL01'if ( $value -match 'S-\w\w\w-SQL\d\d'){ # do something}
un patrón de expresiones regulares coincide en cualquier parte de la cadena de forma predeterminada. Por lo tanto, puede especificar una subcadena que desee EMPAREJAR de la siguiente manera:
$value = 'S-ATX-SQL01'if ( $value -match 'SQL'){ # do something}
Regex es un lenguaje complejo propio y vale la pena investigarlo. Hablo más sobre
-match
y las muchas formas de usar expresiones regulares en otro artículo.,Variations:
-
-match
case-insensitive regex -
-imatch
case-insensitive regex -
-cmatch
case-sensitive regex -
-notmatch
case-insensitive regex not matched -
-inotmatch
case-insensitive regex not matched -
-cnotmatch
case-sensitive regex not matched
-is of type
You can check a value’s type with the
-is
operator.,if ( $value -is ){ # do something}
puede usar esto si está trabajando con clases o aceptando varios objetos en la canalización. Usted podría tener un servicio o un nombre de servicio como su entrada. Luego verifique si tiene un servicio y obtenga el servicio si solo tiene el nombre.,
if ( $Service -isnot ){ $Service = Get-Service -Name $Service}
Variaciones:
-
-is
tipo -
-isnot
no de tipo
de la Colección de los operadores
Cuando se utiliza el anterior operadores con un único valor, el resultado es
$true
o$false
. Esto se maneja de manera ligeramente diferente cuando se trabaja con una colección. Cada elemento de la colección se evalúa y el operador devuelve cada valor que se evalúa como$true
.,PS> 1,2,3,4 -eq 33
Esto todavía funciona correctamente en un
if
declaración. Así que un valor es devuelto por su operador, entonces thewhole sentencia es$true
.$array = 1..6if ( $array -gt 3 ){ # do something}
Hay una pequeña trampa esconde en los detalles aquí que yo necesito señalar. Al usar el operador
-ne
de esta manera, es fácil mirar erróneamente la lógica hacia atrás. Usando-ne
con acollection devuelve$true
si algún elemento de la colección no coincide con su valor.,PS> 1,2,3 -ne 4123
Esto puede parecer un truco, pero tenemos los operadores
-contains
y-in
que manejan esta moreefficiently. Y-notcontains
hace lo que esperas.– contiene
el operador
-contains
comprueba la colección por su valor. Tan pronto como Encuentra una coincidencia, vuelve$true
.$array = 1..6if ( $array -contains 3 ){ # do something}
Esta es la forma preferida de ver si una colección contiene su valor., Usando
Where-Object
(o-eq
) recorre toda la lista cada vez y es significativamente más lento.,Variations:
-
-contains
case-insensitive match -
-icontains
case-insensitive match -
-ccontains
case-sensitive match -
-notcontains
case-insensitive not matched -
-inotcontains
case-insensitive not matched -
-cnotcontains
case-sensitive not matched
-in
The
-in
el operador es igual que el operador-contains
excepto que la colección está en el lado derecho.,$array = 1..6if ( 3 -in $array ){ # do something}
Variations:
-
-in
case-insensitive match -
-iin
case-insensitive match -
-cin
case-sensitive match -
-notin
case-insensitive not matched -
-inotin
case-insensitive not matched -
-cnotin
case-sensitive not matched
Logical operators
Logical operators are used to invert or combine other expressions.,
-no
El
-not
operador invierte una expresión de$false
a$true
o de$true
a$false
. Hereis un ejemplo donde queremos realizar una acción cuandoTest-Path
es$false
.if ( -not ( Test-Path -Path $path ) )
La mayoría de los operadores de los que hablamos tienen una variación en la que no es necesario usar el operador
-not
. Pero todavía hay veces que es útil.!, el operador
puede utilizar
!
como un alias para-not
.if ( -not $value ){}if ( !$value ){}
puede ver
!
más utilizado por personas que provienen de otros lenguajes como C#. Prefiero escribirlo porque me resulta difícil ver cuando miro rápidamente mis scripts.– y
puede combinar expresiones con el operador
-and
. Cuando lo hace, ambos lados deben ser$true
para que toda la expresión sea$true
.,if ( ($age -gt 13) -and ($age -lt 55) )
en ese ejemplo,
$age
debe ser 13 o más para el lado izquierdo y menos de 55 para el lado derecho. Añadí paréntesis adicionales para hacerlo más claro en ese ejemplo, pero son opcionales siempre y cuando la expresión sea simple. Aquí está el mismo ejemplo sin ellos.if ( $age -gt 13 -and $age -lt 55 )
la evaluación ocurre de izquierda a derecha. Si el primer elemento se evalúa como
$false
, sale temprano y no realiza la comparación correcta. Esto es útil cuando necesita asegurarse de que existe un valor antes de usarlo., Por ejemplo,Test-Path
lanza un error si le da una ruta$null
.if ( $null -ne $path -and (Test-Path -Path $path) )
-o
El
-or
permite especificar dos expresiones y devuelve$true
si uno de ellos es$true
.if ( $age -le 13 -or $age -ge 55 )
Al igual que con el operador
-and
, la evaluación ocurre de izquierda a derecha., Excepto que si la primera parte es$true
, entonces la instrucción completa es$true
y no procesa el resto de la expresión.también tome nota de cómo funciona la sintaxis para estos operadores. Necesitas dos expresiones separadas. He visto a los usuarios intentar hacer algo como esto
$value -eq 5 -or 6
sin darse cuenta de su error.– exclusivo de xor o
Este es un poco inusual.
-xor
solo permite evaluar una expresión a$true
., Así que si ambos elementos son$false
o ambos elementos son$true
, entonces toda la expresión es$false
. Otra forma de ver esto es que la expresión es solo$true
cuando los resultados de la expresión son diferentes.es raro que alguien alguna vez use este operador lógico y no puedo pensar en un buen ejemplo como towhy lo usaría.
operadores bit a bit
los operadores bit a bit realizan cálculos en los bits dentro de los valores y producen un nuevo valor como resultado., Enseñar operadores bitwise está más allá del alcance de este artículo, pero aquí está la lista thethem.
-
-band
binary and -
-bor
binary OR -
-bxor
binary exclusive OR -
-bnot
binary not -
-shl
shift left -
-shr
shift right
expresiones de PowerShell
podemos usar PowerShell normal dentro de la sentencia condition.,
if ( Test-Path -Path $Path )
Test-Path
devuelve$true
o$false
cuando se ejecuta. Esto también se aplica a los comandos que devuelven otros valores.if ( Get-Process Notepad* )
se evalúa como
$true
si hay un proceso devuelto y$false
si no hay nada., Es perfectamente válido usar expresiones de canalización u otras instrucciones de PowerShell como esta:if ( Get-Process | Where Name -eq Notepad )
estas expresiones se pueden combinar entre sí con los operadores
-and
y-or
, pero puede que tenga que usar paréntesis para dividirlas en subexpresiones.if ( (Get-Process) -and (Get-Service) )
Comprobación para $null
Tener un resultado o de un
$null
valor se evalúa a$false
en elif
declaración., Cuando se comprueba específicamente$null
, es una buena práctica colocar el$null
en el lado izquierdo.if ( $null -eq $value )
hay bastantes matices al tratar con valores
$null
en PowerShell. Si estás interesado en bucear más profundo, tengo un artículo sobre todo lo que querías saber sobre null null.asignación de variables
casi olvidé agregar esta hasta que Prasoon Karunan V me la recordó.,
if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}
normalmente, cuando se asigna un valor a una variable, el valor no se pasa a la canalización o a la consola. Cuando realiza una asignación de variable en una subexpresión, se pasa a la línea de transmisión.
PS> $first = 1PS> ($second = 2)2
Ver cómo el
$first
asignación no tiene salida y la de$second
asignación de qué? Cuando una asignación se realiza en una instrucciónif
, se ejecuta igual que la asignación$second
anterior., Aquí está una cleanexample sobre cómo se podría utilizar es:if ( $process = Get-Process Notepad* ){ $process | Stop-Process}
Si
$process
se les asigna un valor, entonces la instrucción$true
y$process
se detuvo.asegúrese de no confundir esto con
-eq
porque esto no es una comprobación de igualdad. Esta es una característica de moreobscure que la mayoría de la gente no se da cuenta de que funciona de esta manera.,ruta de ejecución alternativa
la instrucción
if
le permite especificar una acción no solo para cuando la instrucción es$true
, sino también para cuando es$false
. Aquí es donde entra en juego la instrucciónelse
.else
la instrucción
else
siempre es la última parte de la instrucciónif
cuando se usa.en este ejemplo, comprobamos el
$path
para asegurarnos de que es un archivo. Si encontramos el archivo, lo movemos. Si no, escribimos una advertencia., Este tipo de lógica de ramificación es muy común.anidado si
las instrucciones
if
yelse
toman un bloque de script, por lo que podemos colocar cualquier comando de PowerShell dentro de la instrucción, incluyendo otra instrucciónif
. Esto le permite hacer uso de la lógica mucho más complicada.en este ejemplo, primero probamos el camino feliz y luego tomamos medidas al respecto. Si eso falla, hacemos otra comprobación y para proporcionar información más detallada al usuario.
elseif
no estamos limitados a una sola comprobación condicional., Podemos encadenar
if
yelse
statementstogether en lugar de anidarlos usando la instrucciónelseif
.la ejecución ocurre de arriba a abajo. La instrucción top
if
se evalúa primero. Si son$false
, se mueve hacia abajo a la siguienteelseif
oelse
en la lista. Esa últimaelse
es la acción predeterminada a tomar si ninguna de las otras devuelve$true
.,switch
en este punto, necesito mencionar la instrucción
switch
. Proporciona una sintaxis alternativa para hacer comparaciones múltiples con un valor. Conswitch
, se especifica una expresión y el resultado se compara con varios valores diferentes. Si uno de esos valores coincide, se ejecuta el bloque de código coincidente. Echa un vistazo a este ejemplo:$itemType = 'Role'switch ( $itemType ){ 'Component' { 'is a component' } 'Role' { 'is a role' } 'Location' { 'is a location' }}
hay tres valores posibles que pueden coincidir con el
$itemType
. En este caso, coincide conRole
., Usé un ejemplo simple para darle algo de exposición al operadorswitch
. Hablo más sobre todo lo que siempre quisiste saber sobre la declaración switch en otro artículo.Pipeline
la pipeline es una característica única e importante de PowerShell. Cualquier valor que no sea suppressedor o asignado a una variable se coloca en la canalización. El
if
nos proporciona una forma de aprovechar la canalización de una manera que no siempre es obvia.,$discount = if ( $age -ge 55 ){ Get-SeniorDiscount}elseif ( $age -le 13 ){ Get-ChildDiscount}else{ 0.00}
cada bloque de script coloca los resultados de los comandos o el valor en la canalización. Luego asignamos el resultado de la instrucción
if
a la variable$discount
. Ese ejemplo podría haber asignado fácilmente esos valores a la variable$discount
directamente en cada bloque de scripts. No puedo decir que use esto con la instrucciónif
a menudo, pero tengo un ejemplo donde Usé esto recientemente.,Array inline
Tengo una función llamada Invoke-SnowSql que lanza un ejecutable con varios documentos de línea de comandos. Aquí hay un clip de esa función donde construyo la matriz de argumentos.
las variables
$Debug
y$Path
son parámetros de la función que proporciona el usuario final.Los evalúo en línea dentro de la inicialización de mi matriz. Si$Debug
es true, entonces esos valores caen en el$snowSqlParam
en el lugar correcto. Lo mismo se aplica a la variable$Path
.,simplificar operaciones complejas
es inevitable que se encuentre en una situación que tiene demasiadas comparaciones para verificar y su instrucción
If
se desplaza fuera del lado derecho de la pantalla.pueden ser difíciles de leer y que te hacen más propenso a cometer errores. Hay algunas cosas que podemos hacer al respecto.
continuación de línea
hay algunos operadores en PowerShell que le permiten ajustar el comando a la siguiente línea., Los operadores lógicos
-and
y-or
son buenos operadores para usar si desea romper su expresión en múltiples líneas.todavía hay mucho que hacer allí, pero colocar cada pieza en su propia línea hace una gran diferencia.Generalmente uso esto Cuando obtengo más de dos comparaciones o si tengo que desplazarme a la derecha para leer cualquiera de la lógica.
pre-cálculo de resultados
podemos tomar esa instrucción de la instrucción
if
y solo comprobar el resultado.esto se siente mucho más limpio que el ejemplo anterior., También se le da la oportunidad de usar un nombre avariable que explica qué es lo que realmente está comprobando. Este es también un ejemplo de código de auto-documentación que guarda comentarios innecesarios.
múltiples sentencias if
podemos dividir esto en varias sentencias y verificarlas una a la vez. En este caso, utilizamos aflag o una variable de seguimiento para combinar los resultados.
tuve que invertir la lógica para que la lógica de la bandera funcionara correctamente. Cada evaluación es una declaración individual
if
., La ventaja de esto es que cuando se está depurando, se puede decirexactly lo que la lógica está haciendo. Pude agregar mucho mejor verbosidad al mismo tiempo.La desventaja obvia es que es mucho más código para escribir. El código es más complejo de observar como toma una sola línea de lógica y la explota en 25 o más líneas.
usando functions
También podemos mover toda esa lógica de validación a una función. Mira lo limpio que se ve en aglance.,
if ( Test-SecureDriveConfiguration -ADUser $user ){ # do something}
todavía tiene que crear la función para hacer la validación, pero hace que este código sea mucho más fácil de trabajar. Hace que este código sea más fácil de probar. En sus pruebas, puede simular la llamada a
Test-ADDriveConfiguration
y solo necesita dos pruebas para esta función. Uno donde devuelve$true
y otro donde devuelve$false
. Probar la otra función es más simple porque es muy pequeña.el cuerpo de esa función todavía podría ser el de un liner con el que empezamos o la lógica explotada que usamos en la última sección., Esto funciona bien para ambos escenarios y le permite cambiar fácilmente thatimplementation más adelante.
manejo de errores
un uso importante de la instrucción
if
es comprobar las condiciones de error antes de ejecutar intoerrors. Un buen ejemplo es comprobar si una carpeta ya existe antes de intentar crearla.if ( -not (Test-Path -Path $folder) ){ New-Item -Type Directory -Path $folder}
me gusta decir que si espera que ocurra una excepción, entonces no es realmente una excepción. Así que compruebe sus valores y valide sus condiciones donde pueda.,
si desea sumergirse un poco más en el manejo real de excepciones, tengo un artículo sobre todo lo que siempre quiso saber sobre las excepciones.
palabras finales
la instrucción
if
es una instrucción simple, pero es una pieza fundamental de PowerShell. Te encontrarás usando esto varias veces en casi cada script que escribas. Espero que tenga una mejor comprensión de lo que tenía antes. -