Powershell不扩展Foreach-Object中的变量字符串

时间:2015-04-09 16:12:32

标签: powershell

我正在尝试使用Powershell字符串扩展来模拟一些字符串。当我使用字符串文字时它很好,但是当我将字符串作为变量传递时它不起作用。我需要做些什么不同的事情?

$list = Get-Process

# this works fine
$list | ForEach-Object {"$($_.ProcessName)"}

# this doesn't
$template = "$($_.ProcessName)"
$list | ForEach-Object {$template}

4 个答案:

答案 0 :(得分:2)

你不能只用普通的字符串来做这件事。但是,您可以将字符串放在scriptblock内,然后使用call operator &调用它:

$template = {"$($_.ProcessName)"}
$list | ForEach-Object {&$template}

答案 1 :(得分:1)

让我们从第一个问题开始。

运行$template = "$($_.ProcessName)"后,您希望$template的值为字符串$($_.ProcessName),但不是。{/ p>

> $template = "$($_.ProcessName)"
> "[" + $template + "]"
[]

评估双引号中的表达式(并成为空字符串)。

您需要使用单引号来阻止这种情况。

> $template = '$($_.ProcessName)'
> "[" + $template + "]"
[$($_.ProcessName)]

确定。那么让我们在你的foreach循环中尝试一下吗?

> $list = Get-Process
> $template = '$($_.ProcessName)'
> $list | ForEach-Object {$template}
$($_.ProcessName)
$($_.ProcessName)
$($_.ProcessName)
$($_.ProcessName)
...
嗯......不是我们想要的。那是因为powershell没有将字符串作为表达式进行评估。所以我们需要强迫它这样做。

您可以使用Invoke-Expression

执行此操作
> $list = Get-Process
> $template = '$($_.ProcessName)'
> $list | ForEach-Object {Invoke-Expression $template}
procA
procB
procC
...

(您也可以使用脚本块,因为iCodez在他们的答案中指出。我不能评论一种方法相对于另一种方法的相对优点。我认为脚本块可能更具可扩展性和有用性。)

答案 2 :(得分:0)

当您在$template生成字符串时,$_不存在。因此,您将获得一个空字符串。

你最好使用:

$template = "{0}"
$list | ForEach-Object { $template -f $_.ProcessName }

这使用.NET的string.Format模板。传递给-f的参数是一个对象数组,所以如果你想要更多,你可以用逗号分隔它们:

"{0}-{1}" -f "One", "Two"

答案 3 :(得分:0)

您还可以强制进行字符串扩展。您需要使用单引号定义字符串,以便在此时不进行扩展,然后在循环中使用:

$ExecutionContext.InvokeCommand.ExpandString($template)

对于您正在做的事情,其他答案可能更可取。如果我不知道模板中有哪些变量,那么我使用这个,所以使用-f并不是一个真正的选项。