Режимы синтаксического анализа PowerShell: режим аргумента (команды) или режим выражения
Может кто-нибудь объяснить, почему при возврате $ false из функции powershell вы не можете использовать оператор сравнения, чтобы определить, вернула ли функция $ false, но когда вы возвращаете $ true, сравнение оценивается как $ true?
function boolean {
return $false
}
boolean -eq $false
function boolean {
return $true
}
boolean -eq $true
>>>False
>>>True
Вы можете обойти это, установив вызов функции для переменной, но мне было интересно, кто-нибудь может объяснить, что здесь происходит под капотом?
function boolean {
return $false
}
$bool = boolean
$bool -eq $false
function boolean {
return $true
}
$bool = boolean
$bool -eq $true
>>>True
>>>True
2 ответа
PowerShell имеет два основных режима анализа:
режимаргумента, который работает как традиционные оболочки
- В режиме аргументов первый токен интерпретируется как имя команды (например, имя командлета, имя функции или имя файла исполняемого файла), за которым следует разделенный пробелами список аргументов.
режимвыражения, который работает как традиционные языки программирования.
Бег Get-help about_Parsing
обеспечивает введение в эти режимы; короче говоря,этопервый токен, который определяет, какой режим применяется.
Также обратите внимание, что данный оператор может состоять из частей, которые анализируются в любом режиме.
boolean -eq $false
анализируется в режимеаргумента, потому что егопервый токен выглядит какимя команды(идентификатор, который может быть именем программы, именем командлета, именем функции или псевдонимом).
Следовательно,-eq
а также$false
интерпретируются как аргументы (значения параметров) для передачи в функциюboolean
,
Так как ваш boolean
функции определены таким образом, чтобы не принудительно передавать значения только объявленным параметрам, аргументы фактически игнорируются, и результатом оператора является любой вывод функции ($false
или же $true
).
Как продемонстрировано в ответе Майка Шепарда, вы можете заставить функцию принудительно использовать только объявленные параметры (включая ни один) с param()
блок украшен [CmdletBinding()]
атрибут, который по крайней мере приведет к ошибке, если вы непреднамеренно передали аргументы параметру-без boolean
функция.
Вы можете обойти это, установив вызов функции для переменной
$bool = boolean # execute function and capture result in variable
$bool -eq $false # use variable in the comparison
Это работает потому, что -eq
заявление начинается с$
- ссылка на переменную в этом случае - которая заставляет PowerShell анализировать в режиме выражения, где -eq
признается как оператор и $false
как его RHS.
Тем не менее, нет необходимости в этом промежуточном этапе:
Чтобы заставить фрагмент кода интерпретироваться как выражение, заключите его в(...)
:
(boolean) -eq $false # Calls function 'boolean' and uses result as LHS of -eq
(...)
инициирует новый контекст синтаксического анализа (который сам по себе анализируется в режиме аргумента или выражения, опять же в зависимости от 1-го токена) и обрабатывает результат как выражение. который затем позволяет использовать его как часть большего выражения, такого как операнд -eq
оператор или в качестве аргумента команды.
PowerShell видит -eq как имя параметра, передаваемого в "логическую" функцию.
Чтобы увидеть это, вы можете поместить вызов функции в parens:
function boolean {
return $false
}
(boolean) -eq $false
function boolean {
return $true
}
(boolean) -eq $true
Или вы можете сделать это расширенной функцией, чтобы получить ошибку с отсутствующим параметром (-eq):
function boolean {
[CmdletBinding()]
Param()
return $false
}
boolean -eq $false
function boolean {
[CmdletBinding()]
Param()
return $true
}
boolean -eq $true