Reputation: 4016
I have a script with a foreach loop over an array, and it should be using a string that has the current object in it. But the string isn't expanding properly.
$Patterns = ("An", "array", "of", "strings")
$Template = "The current item is $_"
$Patterns | foreach { Does-Something $Template }
The output of does-something just puts the template string up to the variable, but doesn't insert it. This works if I use a foreach statement and an explicit variable name. What do I need to change to make this work?
EDIT:
Ok, I had a mistake in understanding, and left out something important, so let me post the actual code I'm using:
$OutFile = "C:\Searched.txt"
$Path = "C:\Dev\Folder\To\Search"
$Patterns = ( "Big", "Array", "of", "things", "to", "search" )
$exp = @{Expression={$_.FileName};Label="File Name"}, `
@{Expression={$_.LineNumber};Label="Line #"}, `
@{Expression={$_.Path.Substring($Path.Length)};Label="Path ($Path)"}, `
@{Expression={$_.Line.Trim()};Label="Line ($_)"}
$Patterns | foreach {
get-childitem ($Path + "*") -include *.cs -recurse `
| select-string -pattern ($_ + "TableAdapter") `
| format-table $exp -AutoSize }
So the issue is that I foolishly have $_
embedded into the expression hashtable, which is being passing into format-table, but format-table needs the $_
expression itself. So I'm not actually able to access the outer scope with the string I need.
Now, is there a way to get around that?
Upvotes: 0
Views: 5524
Reputation: 18176
Try
$Patterns | foreach {Does-Something $executioncontext.InvokeCommand.ExpandString($Template)}
This should do the string expansion for you.
Upvotes: 2
Reputation: 29944
It seems like what you really need is a function evaluated at the time the loop is run. Maybe you can make $exp
a scriptblock
. A simple example of what I mean:
PS C:\> $func = [scriptblock]{ 'prefix' + $_ }
PS C:\> @('x', 'y', 'z') | Foreach-object { Write-host (& $func) }
prefixx
prefixy
prefixz
PS C:\>
Or just define a function:
PS C:\> function func() { 'prefix' + $_ }
PS C:\> @('x', 'y', 'z') | Foreach-object { Write-host (func) }
prefixx
prefixy
prefixz
PS C:\>
By referencing $_
in a scriptblock or function, it will be evaluated when called and not before.
Or if you prefer, you may define the scriptblock
/function to take the input object as a parameter:
PS C:\> function func($x) { 'prefix' + $x }
PS C:\> @('x', 'y', 'z') | Foreach-object { Write-host (func $_) }
prefixx
prefixy
prefixz
PS C:\>
Upvotes: 0
Reputation: 29479
I don't see that you use $_
from outer scope. But let's assume that you would like to have last column with name "Line for pattern $_"
, so you would use outer scope from foreach
, than the simplest solution would be just change the label in each iteration:
...
$Patterns | foreach {
$exp[-1].Label = "Line for pattern $_" # <<- this one
get-childitem ($Path + "*") -include *.cs -recurse `
| select-string -pattern ($_ + "TableAdapter") `
| format-table $exp -AutoSize
}
Upvotes: 0