Question

I would like to retrieve the contents of a file, filter and modify them and write the result back to a file. I do this:

PS C:\code> "test1" >> test.txt
PS C:\code> "test2" >> test.txt
PS C:\code> $testContents = Get-Content test.txt
PS C:\code> $newTestContents = $testContents | Select-Object {"abc -" + $_}
PS C:\code> $newTestContents >> output.txt

output.txt contains

"abc -" + $_                                                                                                           
------------                                                                                                           
abc -test1                                                                                                             
abc -test2             

What gives with that first line? It's almost like foreach gives back an IEnumerable - but $newTestContents.GetType() reveals it is an object array. So what gives? How can I get the array to output normally without the strange header.

Also bonus points if you can tell me why $newTestContents[0].ToString() is a blank string

Was it helpful?

Solution

Use ForEach instead of the Select-Object

OTHER TIPS

Also bonus points if you can tell me why $newTestContents[0].ToString() is a blank string

If you look at its type, it is a PSCustomObject e.g.

PS> $newTestContents[0].GetType().FullName
System.Management.Automation.PSCustomObject

If you look at PSCustomObject's ToString() impl in Reflector you see this:

public override string ToString()
{
    return "";
}

Why it does this, I don't know. However, it is probably better to use string type coercion in PowerShell e.g.:

PS> [string]$newTestContents[0]
@{"abc -" + $_=abc -test1}

Perhaps you were looking for this result though:

PS> $newTestContents | %{$_.{"abc -" + $_}}
abc -test1
abc -test2

This demonstrates that when you use Select-Object with a simple scriptblock the contents of that scriptblock form the new property name on the PSCustomObject that is created. In general, Nestor's approach is the way to go but in the future if you need to synthensize properties like this then use a hashtable like so:

PS> $newTestContents = $testContents | Select @{n='MyName';e={"abc -" + $_}}
PS> $newTestContents

MyName
------
abc -test1
abc -test2


PS> $newTestContents[0].MyName
abc -test1
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top