header
header Register : : Login header
header
divider
menuleft
menuright
submenu
left

[August 25th, 2008] Check the home page regarding PowerShell related news from a brand new sponsor: Idera

error with foreach/foreach-object
Last Post 24 Jun 2008 08:08 PM by halr9000. 11 Replies.
Printer Friendly
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Author Messages
PasdargentUser is Offline
New Member
New Member
Posts:6
Avatar

--
19 Jun 2008 07:21 PM  

It's my understanding that aliases and the cmdlets they represent behave the same way and use the same syntax.  However, I'm running into an issue with foreach.  The following code gives me no error:

 

foreach($URL in $URLs) {p>
<p>some codep>
<p>}

 

 

However, I get "unexpected token 'in' in expression or string" if I use this code:

 

foreach-object($URL in $URLs) {p>
<p>some codep>
<p>}

 

 

I don't have anything in a profile that would usurp the alias "foreach" and when I do "help foreach" it does give me the reference information for foreach-object.  Any ideas or insight someone can share?

PowerShell 1.0

Windows XP w/ SP2

2 GB RAM



DonJUser is Offline
PowerShell MVP
Basic Member
Basic Member
Posts:134
Avatar

--
19 Jun 2008 07:26 PM  
ForEach-Object doesn't use that syntax - it is not a replacement for ForEach.

$URLs | ForEach-Object { $_.whatever() }

works. You can only use the "$x in $y" syntax as in your first example.


- Don Jones
www.ConcentratedTech.com
Subscribe (RSS) or visit for weekly PowerShell tips and lessons
DonJUser is Offline
PowerShell MVP
Basic Member
Basic Member
Posts:134
Avatar

--
19 Jun 2008 07:27 PM  
(BTW, what you're seeing are some parsing tricks, and the help doesn't make this at all clear - foreach is intended to be used in the way foreach works in C#; foreach-object is a cmdlet intended to be used in pipeline one-liners, for example)


- Don Jones
www.ConcentratedTech.com
Subscribe (RSS) or visit for weekly PowerShell tips and lessons
PasdargentUser is Offline
New Member
New Member
Posts:6
Avatar

--
19 Jun 2008 07:28 PM  

Does that mean I am confusing a built-in PoSh function (foreach) with an alias of similar name?



DonJUser is Offline
PowerShell MVP
Basic Member
Basic Member
Posts:134
Avatar

--
19 Jun 2008 07:31 PM  
Well, it's confusing for sure.

foreach is an alias to ForEach-Object - but when it's used in the pipeline it uses the same syntax:

$collection | ForEach-Object { $_.something() }
$collection | foreach { $_.something() }

Are both valid. When you're using it as a scripting construct, however, PowerShell's parser allows this:

foreach ($item in $collection) {
$item.something()
}

I find it confusing, myself. It's just one of those little gotchas you have to remember.


- Don Jones
www.ConcentratedTech.com
Subscribe (RSS) or visit for weekly PowerShell tips and lessons
DonJUser is Offline
PowerShell MVP
Basic Member
Basic Member
Posts:134
Avatar

--
19 Jun 2008 07:32 PM  
BTW, as a rule I tend to either use ForEach-Object or % in pipelines. If I'm in a script, I just use foreach. Helps me keep it straight in my head.


- Don Jones
www.ConcentratedTech.com
Subscribe (RSS) or visit for weekly PowerShell tips and lessons
PasdargentUser is Offline
New Member
New Member
Posts:6
Avatar

--
19 Jun 2008 07:37 PM  
Don, thanks for the info. I was going to apologize for the newbie question but I can see now that it's a bit confusing itself. Thank you for the tip on pipeline vs scripting. I was wondering why PrimalScript wasn't changing foreach into foreach-object when I tried to convert alias to cmdlets.


KarlUser is Offline
New Member
New Member
Posts:11
Avatar

--
19 Jun 2008 07:40 PM  

I see a couple of mistakes.. one is you forgot the $ in $URLS in the second,

but the main one is a common confusion with powershell..

foreach($a in $y) in a LANGUAGE CONSTRUCT of powershell, while foreach-object is a CMDLET that just happens to come with powershell which implements funtional programming MAP concepts http://en.wikipedia.org/wiki/Map_%28higher-order_function%29 .

to muddy the waters foreach-object has an alias set as foreach as well..

 

so when you are doing a straight language loop you can use foreach($i in $y)

but when you are using the pipeline you use foreach-object

i.e

1..10 | foreach-object { $_ * $_ }  will output the square of whatever is coming through the pipeline..

there are different aliases for foreach-object , namely foreach and % so the above line could also be written

1..10 | foreach { $_ * $_ } 
or
1..10 | % { $_ * $_ } 

you can read the help in powershell, i think about_foreach and foreach-object's help

foreach-object can also take in some scriptblocks to run at the start, and at the end as well..

i.e what you saw above is putting the scriptblock as the -process parameter

so

1..10 | foreach-object  -process { $_ * $_ } 

is exactly the same but you could do

1..10 | foreach-object  -start { write-host "being of loop" } -process { $_ * $_ }  -end {write-host "end of loop " }

or you can just have the parameters implicit by order

1..10 | foreach-object  { write-host "being of loop" } { $_ * $_ }  {write-host "end of loop " }

-Karl



DonJUser is Offline
PowerShell MVP
Basic Member
Basic Member
Posts:134
Avatar

--
19 Jun 2008 07:40 PM  

No sweat. Earlier releases of PrimalScript did make that replacement - I asked them to make it an exception because of this very issue.



- Don Jones
www.ConcentratedTech.com
Subscribe (RSS) or visit for weekly PowerShell tips and lessons
kctElginUser is Offline
New Member
New Member
Posts:24
Avatar

--
24 Jun 2008 04:03 PM  

File got dropped as well?


Attachment: 16244081254.txt

halr9000User is Offline
PowerShell MVP, Site Admin
Basic Member
Basic Member
Posts:335
Avatar

--
24 Jun 2008 08:01 PM  
Ok, I'll take the foreach one...

Foreach at the beginning of a line is a statement. Foreach-Object is a cmdlet. Foreach inside a pipeline is always an alias for Foreach-Object.

Foreach works this way:

foreach ($item in $collection) or
foreach ($item in (sub-expression e.g. "dir") )

Each variant is followed by a script block enclosed in braces. The iteration variable ($item in this example) changes as the collection or sub-expression is processed.

Foreach-Object _only works in a pipeline. e.g.:

dir | foreach-object { $_ }

Anything can be in the script block, and the automatic variable $_ matches the current object in the pipeline.

Tips:
- Never use the alias foreach! Ever! I wish they had not created the alias at all, it's just confusing. Use % when you want to save typing.
- Use foreach or foreach-object instead of a for loop when you don't need to track progress of the loop. Because of the nature of foreach/foreach-object, you don't know how long the pipeline will continue.
- Use Foreach over foreach-object when you are nesting multiple loops and you must grab a value from a higher level loop. e.g.:

foreach ( $computer in (get-content servers.txt) ) {
foreach ($drive in (gwmi -comp $computer win32_logicaldisk ) {
write-output $computer $drive.size
}
}


Community Director, PowerShellCommunity.org
Co-host, PowerScripting Podcast
Author, TechProsaic
halr9000User is Offline
PowerShell MVP, Site Admin
Basic Member
Basic Member
Posts:335
Avatar

--
24 Jun 2008 08:08 PM  
[OT] I split the pipeline / regex questions off to a new thread. [/OT]


Community Director, PowerShellCommunity.org
Co-host, PowerScripting Podcast
Author, TechProsaic
You are not authorized to post a reply.

Active Forums 4.1
right
   
footer Sponsored by Quest Software • SAPIEN Technologies • ShellTools, LLC • Microsoft Windows Server 2008 footer
footer