Home > Back-end >  How to make ForEach-Object start counting from 1 instead of 0
How to make ForEach-Object start counting from 1 instead of 0

Time:09-17

I have a nice string that looks like this:

Get-Azsubscription | ForEach-Object {"$($a).) $($_.Name)"; $a  }

It allows me to count how many subscriptions I have on Azure and it adds a number to it. The problem is that the counter starts from 0, which is in my case .) :

enter image description here

How to make that counter start to count from 1 and not from 0?

CodePudding user response:

The ForEach-Object cmdlet takes an additional -Begin block you can use to initialize any variable you want to use:

Get-Azsubscription | ForEach-Object -Begin { $a = 1 } -Process {"$a.) $($_.Name)"; $a  }

CodePudding user response:

To complement Mathias R. Jessen's effective solution:

Indeed you should explicitly initialize your $a variable with the desired starting value.

If $a is uninitialized, as it was in your case:

  • Using it inside an expandable string ("$a") makes it expand to the empty string.

  • The first time you apply to it, it is fist implicitly initialized (as an [int] with) value 0, so that it receives value 1. Subsequent operations then perform as usual.

While using a -Begin block with ForEach-Object in order to initialize the variable is conceptually clear, the caveat is that the variable is not scoped to that statement, and lives on afterwards.

Thus, the alternative is to simply initialize it before calling ForEach-Object.

You can also streamline the command a bit by incorporating the operation into the expandable string, but note that you then need to enclose it in (...), in addition to $(...); the reason is that a operation produces no output by default, except if you apply (...), the grouping operator, to pass the value through.

Therefore:

$a = 0 # Initialize the sequence number
Get-Azsubscription | ForEach-Object { "$((  $a)).) $($_.Name)" }

Note the initialization to 0 in combination with the prefix version of , the increment operator, so that incrementing to 1 and outputting that value happens on the first iteration.


A simplified example:

$a = 0 # Initialize the sequence number
[pscustomobject] @{ Name='foo' }, [pscustomobject] @{ Name='bar' } |
   ForEach-Object { "$((  $a)).) $($_.Name)" }

Output:

1.) foo
2.) bar

Finally, a perhaps more PowerShell-idiomatic solution that constructs custom objects for display, which PowerShell automatically formats nicely for you:

$a = 0 # Initialize the sequence number
[pscustomobject] @{ Name='foo' }, [pscustomobject] @{ Name='bar' } |
   ForEach-Object { [pscustomobject] @{ '#' =   $a; Name = $_.Name } }

Output:

# Name
- ----
1 foo
2 bar
  • Related