What am I doing wrong in subexpression?

I’m trying to use subexpression and it fails to materialize, what am I doing wrong?

$a = "A", "AA" write-output "Length is $($a|Select -Property length)"

I would expext output to contain something but it’s empty and ends up as "Length is "

Try Count, not Length. And you probably want -ExpandProperty, not -Property.

And sorry, that assumes you’re wanting the number of objects in $a, not the length of the strings in $a. If you want the lengths of the strings, you may have to re-think a bit, as the output will be an array with the same number of integers (lengths) as the input array as string objects.

Changing -Property to -ExpandProperty should work. The pipeline will enumerate the array and output the Length of each string. Those lengths will wind up being a space-separated list, by default, since you’re then essentially casting an array to a string.

I tried length and it still does not work. If I just do write-output $return | Select -Property Length then it works fine, it’s just if I wrap it as subexpression inside string where it stops working.

PS C:\Users\g> $($a|Select -Property Length)

                                                                                                                                                                      Length
                                                                                                                                                                      ------
                                                                                                                                                                           1
                                                                                                                                                                           2


PS C:\Users\g> "Length is $($a|Select -Property Length)"
Length is  



It’ important to understand that -Property causes Select-Object to still output OBJECTS having, in your case, just one property. PowerShell doesn’t have a good way of casting that collection of objects into a string, which s what the subexpression requires it to do. About the only time the shell will do that successfully is if the objects have a Name property; in v3 and later, there’s a hardcoded behavior for that property.

Our suggestion to use -Expand instead is because -Expand extracts the contents of the specified property, returning it as a simple value (that’s not a technically accurate phrase, but roll with it). In this case, because Length contains integers, -Expand would return a list of plain integers, not objects having a Length property, which is what -Property was doing. PowerShell knows how to cast integers as strings, as the subexpression requires, and so it’ll work. As Dave notes, you’ll get a space-delimited list, because that’s how PowerShell turns an array of something into a string list.

BTW, to really illustrate this, run the following from the console and pay close attention to the output of each:

$a | Select -Property Length
$a | Select -Expand Length

See the difference? It’s important, and it’s one of the bigger “gotchas” in PowerShell. I think it’s even in our “gotchas” ebook.

Thanks, this works.
I wish sometimes Powershell would not be so much catering to be user friendly and fail consistently on this sort of castings instead. Confuses the hell out of anybody who did .NET coding before this crazy casts.

For me the -ExpandProperty option works fine, here is the code I used:

$a = "A", "AA"
write-output "Length is $($a|Select -ExpandProperty length)"
Length is 1 2

If you want the number of strings in your array you could use .Count for example:

write-output "Length is $($a.count)"

Alternatively you could also use the following notation:

write-output "Length is $(,$a | Select -ExpandProperty Count)"

Yeah, I hear that a lot ;). It’s kind of an endemic difference between “programming language” and “shell.” Which is why anytime someone calls PowerShell a “scripting language” I go suborbital. The technical term isn’t “casting,” because that would imply a strict set of casting rules and failures; I think the term is “munging.”

For the most part, when you cast something to a string in PowerShell, it winds up just calling the ToString() method on it. The objects output by Select-Object -Property Length produce blank strings:

$objects = $a | Select -Property Length
$objects[0].ToString()

Which is why you wind up with nothing visible in your original code.