Каковы PowerShell-эквиваленты Bash's && и || операторы? - PullRequest
25 голосов
/ 10 марта 2010

В Bash я легко могу сделать что-то вроде

command1 && command2 || command3

, что означает запуск команды1, и если команде1 удается выполнить команду2 и если команде1 не удается запустить команду3.

Что такое эквивалент в PowerShell?

Ответы [ 3 ]

21 голосов
/ 24 января 2017

Через много лет после того, как вопрос был впервые задан, позвольте мне обобщить состояние дел с PowerShell v5.1 :

  • Операторы управления Bash's / cmd * && и || не имеют эквивалентов PowerShell , и поскольку вы не можете определять пользовательские операторы в PowerShell, не годится обходные

    • Используйте отдельные команды (в отдельных строках или через ;) и явно проверяйте статус успешности каждой команды с помощью автоматической переменной $?, такой как:
      command1 -arg1 -arg2; if ($?) { command2 -arg1 } # equivalent of &&
      command1 -arg1 -arg2; if (-not $?) { command2 -arg1 } # equivalent of ||

    • См. Ниже, почему PowerShell -and и -or обычно не решение.

  • Был разговор о добавлении их некоторое время назад, но, похоже, он никогда не занимал верхнюю часть списка.

    • Теперь, когда PowerShell вышел с открытым исходным кодом, и проблема была открыта на GitHub .
    • Токены && и || в настоящее время зарезервированы для будущего использования в PowerShell, поэтому есть надежда, что тот же синтаксис, что и в Bash, может быть реализован.
      (Начиная с PSv5.1, попытка что-то вроде 1 && 1 выдает сообщение об ошибке The token '&&' is not a valid statement separator in this version.)

Почему PowerShell -and и -or не могут заменить && и ||:

Операторы управления Bash && (короткое замыкание логического И) и || (короткое замыкание логического ИЛИ) неявно проверяют статус успешности команд по их кодам выхода, без вмешательства в их выходные потоки ; e.g.:

ls / nosuchfile && echo 'ok'

Все, что выводит ls - и вывод stdout (файлы в /), и вывод stderr (сообщение об ошибке при попытке доступа к несуществующему файлу nosuchfile) - пропущено через , но && проверяет (невидимый) код выхода команды ls, чтобы определить, должна ли выполняться команда echo - RHS оператора управления &&.

ls сообщает о коде выхода 1 в этом случае, сигнализируя ошибка - потому что файл nosuchfile не существует - поэтому && решает, что ls не удалось и, применяя короткое замыкание, решает, что команду echo выполнять не нужно.
Обратите внимание, что код выхода 0 сигнализирует об успехе в мире cmd.exe и bash, тогда как любой код выхода , отличный от нуля , указывает на ошибку.

Другими словами: Bash && и || работают полностью независимо от команд * output и действуют только на статус успеха команд.


PowerShell -and и -or, напротив, действуют только на стандартные команды (успех) вывод , потребляют это и затем выводить только логический результат операции ; e.g.:

(Get-ChildItem \, nosuchfile) -and 'ok'

Выше:

  • использует и потребляет success (стандартный) вывод - список \ - и интерпретирует его как Boolean ; непустая входная коллекция считается $true в логическом контексте, поэтому, если есть хотя бы одна запись, выражение оценивается как $true.

    • Однако информация об ошибке , полученная из несуществующего файла nosuchfile , передается , поскольку ошибки отправляются в отдельный поток.
  • Принимая во внимание, что Get-ChildItem \, nosuchfile возвращает непустые выходные данные успеха, LHS оценивается как $true, поэтому -and также оценивает RHS, 'ok', но, опять же, потребляет выводит его и интерпретирует как логическое значение, которое, как непустая строка, также оценивается как $true.

  • Таким образом, общий результат выражения -and равен $true, то есть (единственный успех) output .

Чистый эффект :

  • Результат успеха с обеих сторон выражения -and потребляется во время оценки и, следовательно, эффективно скрыт .

  • Единственным (успешным) выводом выражения является его логический результат , который в данном случае равен $true (который отображается как True в терминале в англоязычных системах).

9 голосов
/ 10 марта 2010

То, что должен делать Bash, это неявное приведение кода завершения команд к логическому значению при передаче логическим операторам. PowerShell этого не делает, но можно создать функцию для переноса команды и создать такое же поведение:

> function Get-ExitBoolean($cmd) { & $cmd | Out-Null; $? }

( $? Это логическое значение, содержащее код успешного завершения последнего выхода )

Имеется два пакетных файла:

#pass.cmd
exit

и

#fail.cmd
exit /b 200

... поведение можно проверить:

> if (Get-ExitBoolean .\pass.cmd) { write pass } else { write fail }
pass
> if (Get-ExitBoolean .\fail.cmd) { write pass } else { write fail }
fail

Логические операторы должны оцениваться так же, как в Bash. Сначала установите псевдоним:

> Set-Alias geb Get-ExitBoolean

Тест:

> (geb .\pass.cmd) -and (geb .\fail.cmd)
False
> (geb .\fail.cmd) -and (geb .\pass.cmd)
False
> (geb .\pass.cmd) -and (geb .\pass.cmd)
True
> (geb .\pass.cmd) -or (geb .\fail.cmd)
True
0 голосов
/ 21 января 2017

Мы можем использовать метод try catch finally вместо метода && в powershell.

try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}
...