2

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

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

Comments

2

Use ForEach instead of the Select-Object

3 Comments

how exactly would I use foreach to create a transform?
George,.. use your same code.. but replace Select-Object by ForEach. It should work as without any other modification.
Ahh, ok thanks. I was thinking from the C# LINQ point of view where ForEach is a void return

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.