- 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.,
-
-eqigualdad insensible a mayúsculas y minúsculas -
-ieqigualdad insensible a mayúsculas y minúsculas -
-ceqigualdad h3>muchos operadores tienen un operador relacionado que está comprobando el resultado opuesto.
-neverifica 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:
-
-necase-insensitive not equal -
-inecase-insensitive not equal -
-cnecase-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 -lesignifica GreaterThan, GreaterThanOrEqual, LessThan y LessThanOrEqual.,eater than or equal, case-insensitive -
-
-cgegreater than or equal, case-sensitive -
-ltless than -
-iltless than, case-insensitive -
-cltmenos que, sensible a mayúsculas y minúsculas -
-lemenos o igual -
-ilemenos o igual, insensible a mayúsculas y minúsculas -
-clemenor 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:
-
-likecomodín insensible a mayúsculas y minúsculas -
-ilikecomodín insensible a mayúsculas y minúsculas -
-clikecomodín> -
-notlikecomodín insensible a mayúsculas y minúsculas no coincidente -
-inotlikecomodín insensible a mayúsculas y minúsculas no coincidente -
-cnotlikecomodín/h3>el operador
-matchle 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
-matchy las muchas formas de usar expresiones regulares en otro artículo.,Variations:
-
-matchcase-insensitive regex -
-imatchcase-insensitive regex -
-cmatchcase-sensitive regex -
-notmatchcase-insensitive regex not matched -
-inotmatchcase-insensitive regex not matched -
-cnotmatchcase-sensitive regex not matched
-is of type
You can check a value’s type with the
-isoperator.,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:
-
-istipo -
-isnotno de tipo
de la Colección de los operadores
Cuando se utiliza el anterior operadores con un único valor, el resultado es
$trueo$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 33Esto todavía funciona correctamente en un
ifdeclaració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
-nede esta manera, es fácil mirar erróneamente la lógica hacia atrás. Usando-necon acollection devuelve$truesi algún elemento de la colección no coincide con su valor.,PS> 1,2,3 -ne 4123Esto puede parecer un truco, pero tenemos los operadores
-containsy-inque manejan esta moreefficiently. Y-notcontainshace lo que esperas.– contiene
el operador
-containscomprueba 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:
-
-containscase-insensitive match -
-icontainscase-insensitive match -
-ccontainscase-sensitive match -
-notcontainscase-insensitive not matched -
-inotcontainscase-insensitive not matched -
-cnotcontainscase-sensitive not matched
-in
The
-inel operador es igual que el operador-containsexcepto que la colección está en el lado derecho.,$array = 1..6if ( 3 -in $array ){ # do something}Variations:
-
-incase-insensitive match -
-iincase-insensitive match -
-cincase-sensitive match -
-notincase-insensitive not matched -
-inotincase-insensitive not matched -
-cnotincase-sensitive not matched
Logical operators
Logical operators are used to invert or combine other expressions.,
-no
El
-notoperador invierte una expresión de$falsea$trueo de$truea$false. Hereis un ejemplo donde queremos realizar una acción cuandoTest-Pathes$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$truepara que toda la expresión sea$true.,if ( ($age -gt 13) -and ($age -lt 55) )en ese ejemplo,
$agedebe 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-Pathlanza un error si le da una ruta$null.if ( $null -ne $path -and (Test-Path -Path $path) )-o
El
-orpermite especificar dos expresiones y devuelve$truesi 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$truey 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 6sin darse cuenta de su error.– exclusivo de xor o
Este es un poco inusual.
-xorsolo permite evaluar una expresión a$true., Así que si ambos elementos son$falseo ambos elementos son$true, entonces toda la expresión es$false. Otra forma de ver esto es que la expresión es solo$truecuando 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.
-
-bandbinary and -
-borbinary OR -
-bxorbinary exclusive OR -
-bnotbinary not -
-shlshift left -
-shrshift right
expresiones de PowerShell
podemos usar PowerShell normal dentro de la sentencia condition.,
if ( Test-Path -Path $Path )Test-Pathdevuelve$trueo$falsecuando se ejecuta. Esto también se aplica a los comandos que devuelven otros valores.if ( Get-Process Notepad* )se evalúa como
$truesi hay un proceso devuelto y$falsesi 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
-andy-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
$nullvalor se evalúa a$falseen elifdeclaración., Cuando se comprueba específicamente$null, es una buena práctica colocar el$nullen el lado izquierdo.if ( $null -eq $value )hay bastantes matices al tratar con valores
$nullen 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)2Ver cómo el
$firstasignación no tiene salida y la de$secondasignación de qué? Cuando una asignación se realiza en una instrucciónif, se ejecuta igual que la asignación$secondanterior., Aquí está una cleanexample sobre cómo se podría utilizar es:if ( $process = Get-Process Notepad* ){ $process | Stop-Process}Si
$processse les asigna un valor, entonces la instrucción$truey$processse detuvo.asegúrese de no confundir esto con
-eqporque 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
ifle 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
elsesiempre es la última parte de la instrucciónifcuando se usa.en este ejemplo, comprobamos el
$pathpara 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
ifyelsetoman 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
ifyelsestatementstogether en lugar de anidarlos usando la instrucciónelseif.la ejecución ocurre de arriba a abajo. La instrucción top
ifse evalúa primero. Si son$false, se mueve hacia abajo a la siguienteelseifoelseen la lista. Esa últimaelsees 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
ifnos 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
ifa la variable$discount. Ese ejemplo podría haber asignado fácilmente esos valores a la variable$discountdirectamente en cada bloque de scripts. No puedo decir que use esto con la instrucciónifa 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
$Debugy$Pathson 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$Debuges true, entonces esos valores caen en el$snowSqlParamen 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
Ifse 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
-andy-orson 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
ify 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-ADDriveConfigurationy solo necesita dos pruebas para esta función. Uno donde devuelve$truey 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
ifes 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
ifes 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. -