В Bash я могу легко сделать что-то вроде
command1 && command2 || command3
что означает запуск команды 1, и если command1 успешно запускает команду2, и если command1 не запускает command3.
Что эквивалентно в PowerShell?
В Bash я могу легко сделать что-то вроде
command1 && command2 || command3
что означает запуск команды 1, и если command1 успешно запускает команду2, и если command1 не запускает command3.
Что эквивалентно в PowerShell?
То, что должно выполняться 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
Обновление: &&
и ||
наконец-то приходят в 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, поэтому есть надежда, что тот же синтаксис, что и в Bash, может быть реализован.1 && 1
выдает сообщение об ошибке The token '&&' is not a valid statement separator in this version.
)-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
в терминале в англоязычных системах).
Мы можем использовать метод try catch finally вместо использования && метод в powershell.
try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}
Вы можете сделать что-то вроде этого, где вы скрываете логический вывод с помощью [void] и получаете только побочный эффект. В этом случае, если $ a или $ b равны нулю, $ c присваивается $ result. Назначение может быть выражением.
$a = ''
$b = ''
$c = 'hi'
[void](
($result = $a) -or
($result = $b) -or
($result = $c))
$result
выход
hi