2010-02-12 13 views
23

C'è già una domanda che risolve il problema (Can I get && to work in Powershell?), ma con una differenza. Ho bisogno di un OUTPUT da entrambi i comandi. Vedi, se corro:esecuzione condizionale (&& e ||) in powershell

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

Non vedrò alcun output, ma messaggi di stderr. E, come previsto, semplicemente digitando:

command1 -arg1 -arg2 -and command2 -arg1 

dà l'errore di sintassi.

+0

Non è '-or' '? – stej

+1

Un OR short-circuiting eseguirà la seconda espressione solo se la prima evalerà a false (fallisce). Sospetto che l'OP voglia che la seconda espressione venga eseguita solo se le prime evalive sono vere (succede) che un cortocircuito e ci dà. –

+0

Chiunque è interessato a Bash in stile '&&' e '' || diventando una parte di PowerShell: si prega di votare per la funzione [qui] (https://windowsserver.uservoice.com/forums/301869-powershell/suggestions/11087898 -i-e-operatori -implement-che-bash-ha). – mklement0

risposta

22

Prova questa:

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

Il $() è una sottoespressione che consente di specificare più istruzioni all'interno tra cui una pipeline. Quindi esegui il comando e condividi a Out-Host in modo che tu possa vederlo. Quindi nella prossima istruzione (l'output effettivo della sottoespressione) output $? cioè il risultato del successo dell'ultimo comando.

BTW il $? funziona bene per i comandi nativi (console exe) ma per i cmdlet lascia qualcosa a desiderare. Cioè, $? sembra solo restituire $ false quando un cmdlet rileva un errore di chiusura. Sembra $? ha bisogno di almeno tre stati (fallito, riuscito e parzialmente riuscito). Quindi, se stai usando i cmdlet, funziona meglio:

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

Questo tipo di colpi ancora. Forse qualcosa di simile sarebbe meglio:

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

Grazie, Keith (a proposito, io uso PSCX e lo trovo fantastico, molte grazie per quelli!). Anche se sembra abbastanza utilizzabile, c'è uno svantaggio rispetto alla pipeline UNIX. Considera quanto segue: 'comando1 && comando2 || command3'. È un modello abbastanza comune, penso. – Andy

+4

Sì, questo è un po 'un trucco rispetto al corretto && e || supporto. –

+0

Dal momento che (almeno) PSV2, errori _non-terminating_ _do_ impostato '$' a '$ false': per esempio,' $ null = Get-Item \, nosuch; $? 'restituisce' $ false'. Nel caso di un errore _terminating_, la riga di comando/lo script si annullerebbero per impostazione predefinita; se fai 'try' /' catch' l'errore, '$?' è '$ false' nel blocco' catch', o, se il blocco 'catch' è vuoto, subito dopo; ad es., prova {throw "terminating err"} catch {}; $? ' – mklement0

2

Per semplificare gli script più passaggi in cui dothis || exit 1 sarebbe davvero utile, io uso qualcosa di simile:

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

doThis; ProceedOrExit 
doNext 

# or for long doos 
doThis 
ProceedOrExit 
doNext 
0

po 'più lungo modo è vedere sotto

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

+0

Non c'è bisogno di 'try' /' catch', perché è necessario solo per _terminating_ errors, che le utilità esterne come 'hostname',' ipconfig' e 'findstr' non possono attivare. Il controllo '$ LASTEXITCODE' è necessario solo se si desidera conoscere il codice di uscita specifico impostato da un'utility esterna: il successo astratto o il fallimento si riflettono in' $? ', Proprio come con i cmdlet nativi. Per inciso: per favore [formatta il tuo codice correttamente] (http://meta.stackexchange.com/a/22189/248777). – mklement0

1
  • /s' cmd&& e || operatori di controllo di Bash non hanno alcun PowerShell equivalenti, e dal momento che non è possibile definire gli operatori personalizzati in PowerShell, ci sono niente soluzioni alternative.

    • La soluzione | Out-Host sede in Keith Hill's answer è un fortemente limitato nel senso che può inviare solo normale uscita di comando alla console (terminale), impedendo l'uscita venga inviato attraverso la tubazione o essere catturato in un variabile o file.

informazioni di Ricerca in this answer di mine.

0

La soluzione più semplice è quella di utilizzare

powershell command1 && powershell command2 

in un guscio cmd. Naturalmente, non è possibile utilizzarlo in uno script .ps1, quindi c'è questa limitazione.

Problemi correlati