#powershell
#powershell
Вопрос:
Я бы хотел, чтобы результирующее значение в $ s было «сейчас, тогда на сегодня»
PS H:> $s = "now is $({if (1 -eq 1){'then'}}) for today"
PS H:> $s
now is if (1 -eq 1){'then'} for today
Комментарии:
1. Что не так с
$s = "now is $(if (1 -eq 1){'then'}) for today"
?
Ответ №1:
Это определенно возможно и довольно просто с подвыражениями
Вы были близки, просто нужно удалить внешний набор фигурных скобок
$s = "now is $(if (1 -eq 1){'then'}) for today"
$s
Комментарии:
1. Большое спасибо. «Закрыть, но без сигары». Я думал, что внешние фигурные скобки будут указывать на то, что это scriptblock . Я должен стараться не быть таким умным.
Ответ №2:
Аргументы скриптового блока с задержкой привязки являются неявной функцией, которая:
only works with parameters that are designed to take pipeline input,
of any type except the following, in which case regular parameter binding happens[1]:
[scriptblock]
[object] ([psobject], however, does work, and therefore [pscustomobject] too)
(no type specified), which is effectively the same as [object]
whether such parameters accept pipeline input by value (ValueFromPipelineBy) or by property name (ValueFromPipelineByPropertyName), is irrelevant.
enables per-input-object transformations via a script block passed instead of a type-appropriate argument; the script block is evaluated for each pipeline object, which is accessible inside the script block as $_, as usual, and the script block's output - which is assumed to be type-appropriate for the parameter - is used as the argument.
Since such ad-hoc script blocks by definition do not match the type of the parameter you're targeting, you must always use the parameter name explicitly when passing them.
Delay-bind script blocks unconditionally provide access to the pipeline input objects, even if the parameter would ordinarily not be bound by a given pipeline object, if it is defined as ValueFromPipelineByPropertyName and the object lacks a property by that name.
This enables techniques such as the following call to Rename-Item, where the pipeline input from Get-Item is - as usual - bound to the -LiteralPath parameter, but passing a script block to -NewName - which would ordinarily only bind to input objects with a .NewName property - enables access to the same pipeline object and thus deriving the destination filename from the input filename:
Get-Item file | Rename-Item -NewName { $_.Name '1' } # renames 'file' to 'file1'; input binds to both -LiteralPath (implicitly) and the -NewName script block.
Note: Unlike script blocks passed to ForEach-Object or Where-Object, for example, delay-bind script blocks run in a child variable scope[2], which means that you cannot directly modify the caller's variables, such as incrementing a counter across input objects.
As a workaround, use a [ref]-typed variable declared in the caller's scope and access its .Value property inside the script block - see this answer for an example.