Каковы эквиваленты PowerShell для Bash && и || операторы?

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

command1 && command2 || command3

что означает запуск команды 1, и если command1 успешно запускает команду2, и если command1 не запускает command3.

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

Ответ 1

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

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

($? - это bool, содержащий успех последнего кода выхода)

Учитывая два командных файла:

#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

Ответ 2

Обновление: && и || наконец-то приходят в PowerShell (Core) - см. этот RFC, предположительно в какой-то момент после v7.


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

  • Операторы управления Bash/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 && (короткое замыкание логического И) и || (короткое замыкание логического ИЛИ) неявно проверяют состояние успешности команд по их кодам выхода, не влияя на их выходные потоки; например.:

ls / nosuchfile && echo 'ok'

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

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

Другими словами: Bash && и || работают полностью независимо от вывода команд и влияют только на статус успешности команд.


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

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

Выше:

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

Вы можете сделать что-то вроде этого, где вы скрываете логический вывод с помощью [void] и получаете только побочный эффект. В этом случае, если $ a или $ b равны нулю, $ c присваивается $ result. Назначение может быть выражением.

$a = ''
$b = ''
$c = 'hi'

[void](
  ($result = $a) -or
  ($result = $b) -or
  ($result = $c))

$result

выход

hi