March 30, 2015 at 7:23 am #23759
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 "
March 30, 2015 at 7:25 am #23761
Try Count, not Length. And you probably want -ExpandProperty, not -Property.
March 30, 2015 at 7:26 am #23762
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.
March 30, 2015 at 7:29 am #23764
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.
March 30, 2015 at 7:29 am #23765
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
March 30, 2015 at 7:45 am #23769
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 [b]collection of objects[/b] 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 [b]extracts the contents of the specified property[/b], 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.
March 30, 2015 at 7:46 am #23770
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.
March 30, 2015 at 7:49 am #23771
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.
March 30, 2015 at 7:50 am #23772
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)"
March 30, 2015 at 7:51 am #23773
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."
March 30, 2015 at 7:52 am #23774
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.ToString()
Which is why you wind up with nothing visible in your original code.
You must be logged in to reply to this topic.