Каковы PowerShell-эквиваленты Bash's && и || операторы?
В Bash я легко могу сделать что-то вроде
command1 && command2 || command3
что означает запуск команды command1, и если command1 удается выполнить command2 и если command1 не удается запустить command3.
Что эквивалентно в PowerShell?
3 ответа
То, что должен делать 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
Через много лет после того, как вопрос был впервые задан, позвольте мне кратко изложить ситуацию с PowerShell v5.1:
Баш /
cmd
"s&&
а также||
операторы управления не имеют эквивалентов 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
тогда как любой ненулевой код выхода указывает на сбой.
Другими словами: Баш &&
а также ||
работают полностью независимо от вывода команд и действуют только на статус успешности команд.
PowerShell - х -and
а также -or
напротив, действуйте только на стандартный (успешный) вывод команды, потребляйте его и затем выводите только логический результат операции; например:
(Get-ChildItem \, nosuchfile) -and 'ok'
Выше:
использует и потребляет успешный (стандартный) вывод - список
\
- и интерпретирует это как логическое значение; непустая входная коллекция считается$true
в логическом контексте, поэтому, если есть хотя бы одна запись, выражение оценивается как$true
,- Тем не менее, информация об ошибке в результате несуществующего файла
nosuchfile
пропущен, потому что ошибки отправляются в отдельный поток.
- Тем не менее, информация об ошибке в результате несуществующего файла
При условии
Get-ChildItem \, nosuchfile
возвращает непустой результат успешной работы, LHS оценивается как$true
, так-and
также оценивает RHS,'ok'
, но, опять же, потребляет свои выходные данные и интерпретирует их как логическое значение, которое, как непустая строка, также оценивается как$true
,Таким образом, общий результат
-and
выражение$true
, который является (единственным успехом) выходным.
Чистый эффект:
Успешный результат с обеих сторон
-and
выражение потребляется во время оценки и, следовательно, эффективно скрыты.Единственным (успешным) выводом выражения является его логический результат, который
$true
в этом случае (что делает какTrue
в терминале в англоязычных системах).
Вы можете сделать что-то вроде этого, где вы скрываете логический вывод с помощью [void] и получаете только побочный эффект. В этом случае, если $a или $b равны нулю, $c присваивается $result. Присвоение может быть выражением.
$a = ''
$b = ''
$c = 'hi'
[void](
($result = $a) -or
($result = $b) -or
($result = $c))
$result
выход
hi
Мы можем использовать метод try catch finally вместо метода && в powershell.
try {hostname} catch {echo err} finally {ipconfig /all | findstr bios}