2010-02-12 12 views
23

Ya hay una pregunta que aborda mi problema (Can I get && to work in Powershell?), pero con una diferencia. Necesito un OUTPUT desde ambos comandos. Ver, si acabo de ejecutar:ejecución condicional (&& y ||) en powershell

(command1 -arg1 -arg2) -and (command2 -arg1) 

No veré ninguna salida, pero los mensajes stderr. Y, como esperaba, simplemente escribiendo:

command1 -arg1 -arg2 -and command2 -arg1 

Da error de sintaxis.

+0

¿No es '-o''? – stej

+1

Un quirófano de cortocircuito solo ejecutará la segunda expresión si el primero evalúa a falso (falla). Sospecho que el OP quiere que la segunda expresión se ejecute solo si las primeras evaluaciones son verdaderas (tiene éxito), lo que nos da un cortocircuito. –

+0

Quien esté interesado en '' && 'y' || 'de estilo Bash convirtiéndose en parte de PowerShell: vote por la característica [aquí] (https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11087898 -implement-the-and-operators-that-bash-has). – mklement0

Respuesta

22

Prueba esto:

$(command -arg1 -arg2 | Out-Host;$?) -and $(command2 -arg1 | Out-Host;$?) 

El $() es una sub-expresión que le permite especificar varias instrucciones dentro incluyendo una tubería. Luego ejecuta el comando y canaliza a Out-Host para que puedas verlo. Luego, en la siguiente declaración (la salida real de la subexpresión) ¿salida $? es decir, el resultado de éxito del último comando.

¿Por cierto $? funciona bien para comandos nativos (exe de consola) pero para cmdlets deja algo que desear. Es decir, $? solo parece devolver $ false cuando un cmdlet encuentra un error de terminación. Parece $? necesita al menos tres estados (fallido, exitoso y parcialmente exitoso). Por lo tanto, si usa cmdlets, esto funciona mejor:

$(command -arg1 -arg2 -ev err | Out-Host;!$err) -and 
$(command -arg1 -ev err | Out-Host;!$err) 

Este tipo de golpes son inmóviles. Tal vez algo como esto sería mejor:

function ExecuteUntilError([scriptblock[]]$Scriptblock) 
{ 
    foreach ($sb in $scriptblock) 
    { 
     $prevErr = $error[0] 
     . $sb 
     if ($error[0] -ne $prevErr) { break } 
    } 
} 

ExecuteUntilError {command -arg1 -arg2},{command2-arg1} 
+0

Gracias, Keith (por cierto, uso PSCX y me parece genial, ¡muchas gracias por eso!). Aunque parece bastante utilizable, hay una desventaja en comparación con la tubería UNIX. Considere lo siguiente: 'command1 && command2 || command3'. Es un patrón bastante común, creo. – Andy

+4

Sí, esto es un poco complicado en comparación con el apropiado && y || apoyo. –

+0

Desde (al menos) PSv2, _no-terminaating_ errors _do_ set '$?' A '$ false': por ejemplo,' $ null = Get-Item \, nosuch; $? 'salidas' $ false'. En el caso de un error _terminating_, la línea de comandos/script abortaría por completo; si haces 'try' /' catch' el error, '$?' es '$ false' en el bloque' catch', o si el bloque 'catch' está vacío, inmediatamente después; por ejemplo, 'try {throw" terminating err "} catch {}; $? ' – mklement0

2

Para simplificar guiones de varios pasos, donde doThis || la salida 1 sería realmente útil, utilizo algo como:

function ProceedOrExit { 
    if ($?) { echo "Proceed.." } else { echo "Script FAILED! Exiting.."; exit 1 } 
} 

doThis; ProceedOrExit 
doNext 

# or for long doos 
doThis 
ProceedOrExit 
doNext 
0

poco más manera es ver más abajo

try {nombre de host; if ($ lastexitcode -eq 0) {ipconfig/all | findstr/i bios}} catch {echo err} finally {}

+0

No es necesario 'try' /' catch', porque solo es necesario para _terminating_ errors, que utilidades externas como 'hostname',' ipconfig' y 'findstr' no se pueden activar. Comprobar '$ LASTEXITCODE' solo es necesario si desea conocer el código de salida específico establecido por una utilidad externa: el éxito o la falta de resumen se refleja en' $? ', Al igual que con los cmdlets nativos. Como comentario: por favor [formatee su código correctamente] (http://meta.stackexchange.com/a/22189/248777). – mklement0

1
  • /&& y || operadores de control cmd 's de Bash tienen NO PowerShell equivalentes, y puesto que no se puede definir operadores personalizados de PowerShell, hay son no hay buenas soluciones.

    • El | Out-Host solución basada en Keith Hill's answer es una muy limitada en que sólo puede enviar la salida de comando normal a la consola (terminal), impidiendo la salida de ser enviado a través de la tubería o de ser capturado en una variable o archivo.

Buscar información de antecedentes en this answer mío.

0

La solución más simple es utilizar

powershell command1 && powershell command2 

en una cáscara de cmd. Por supuesto, no puede usar esto en un script .ps1, entonces existe esa limitación.

Cuestiones relacionadas