Recently I have come upon
a situation that required that I read every other line in a file. While this may sound unusual, believe me, it
is more common than you may think. As such
I had to come up with a Do – While loop.
This loop simply put says “do ‘A’ while ‘B’ is true”

First, as usual we need to create a source file. This file can contain anything, for our purposes
we are going to use this:

Now we are going to
define our first variable:

$source =

This variable is going
to have to be an array by using the ampersand (@) followed by parentheses ():

$source = @()

Inside the parentheses
we need to tell Powershell what exactly is going to be in our array. Since we are using the contents of the
source.txt file, we need to use the Get-Content commandlet to tell it to look
in the file, and grab everything in there:

$source = @(Get-content
source.txt)

Now that we have our
array defined, we can define its length.
This is needed as an escape for our loop. For this we are going to use another
variable:

$length

And define it with a property
of the $source array. Specifically, we
want its length. To get the property of
a variable, simply append a period (.) followed by the attribute:

$length = $source.length

Now we need the
counter. A counter is a common piece of
code that increments every time an action is taken. It has two parts, the first is the initial definition,
and the second is the incrementing commandlet.
General practice is to use “I” for an initial counter, “j” for a nested
counter, and so on and so forth. Four our
purposes we are only using I, and we are setting it with the initial value of “0”:

$i = 0

So far we have defined
our variables with this block of code:

$source = @(get-content
source.txt)

$length = $source.length

$i = 0

Now we are going to
initiate the do-while loop with the “do” commandlet. “Do” must always be followed by braces {} to
encapsulate what we intend for it to do.
This tells Powershell what it is exactly you want done while the “While”
condition is true:

Do{}

Because we want to
count every other line we need to set some conditional statements. For this exercise I am going to use the “If”
condition. If must always be followed by
two things, a condition, and an action. The
condition is encapsulated in Parentheses (), and the action is encapsulated in
braces {}

Do{

If(){}

}

We want to tell Powershell
“If the line is even, then tell me it is even.” For this we need to define what
is odd. In basic arithmetic an even
number is divisible by two with no remainder.
An odd number is divisible by two with a remainder of one. The key here is the remainder. It is always either a 1 or a 0. This is convenient as it gives us a clearly
defined variable that is always either true or false. Four this we use the Percentile operator (%)
followed by a 2. The % returns the
remainder rather than the product of a division, and as such is only a 1 or a 0
if we divide by 2. This needs to be
encapsulated in yet another nested set of parentheses ()

Between the last two
closing parentheses we need to give power shell the condition: “ if the result
of the aforementioned formula is equal to “0”.
In order to indicate this we need to use the –eq (Equals) operator
followed by the value of 0:

If(($i%2) –eq 0){}

So we have told Powershell
that If the reminder of the counter $i divided by 2 is 0, then do this. “This” is what we need to define now. We enter in our action inside the braces that
follow the condition statement. For us,
we are only going to have Powershell display the line, and tell us if the line
is even or odd. So we use the Write-Host
Commandlet to tell it to display the output:

{

Write-Host

}

Now we need to tell it
what to write. Start with the source
array variable, and in brackets tell it which item to select with the counter
variable $i. this tells Powershell that
we are selecting the $i item in the array:

{

Write-Host $source[$i]

}

And to prove our output
is correct, we are going to append “is odd” in quotations after this, remember
to have the space between them or else Powershell will think it’s part of the
$source[$i] variable:

{

Write-Host $source[$i] "is odd"

}

Roll that together with
the condition and you should come up with:

If(($i%2) -eq 0){

Write-Host $source[$i] "is odd"

}

Now that we have gotten
this far we need to rinse and repeat with the even numbers, for this all we
change is the –eq value from a 0 to a 1 and change the odd to an even:

if(($i%2) -eq 1){

Write-Host $source[$i] "is even"

}

Combine them to get a
solution for both possible vaues:

if(($i%2) -eq 0){

Write-Host $source[$i] "is odd"

}

if(($i%2) -eq 1){

Write-Host $source[$i] "is even"

}

And at the end we need
to increment the counter. This is the
second part of a counter function. All
that is needed is the variable name, $i, and a “++” appended to it to tell Powershell
to add 1 to the current value:

$i++

Once we have accomplished
this we nest this inside the braces following the Do commandlet, and we have
our do statement:

do{

if(($i%2) -eq 0){

Write-Host $source[$i] "is odd"

}

if(($i%2) -eq 1){

Write-Host $source[$i] "is even"

}

$i++

}

With any do statement
we need to give it an ending condition as I stated earlier. This tells Powershell to do “this” until “that”
condition is met. For this we use “While”. While is always followed by parentheses that
encapsulate the desired condition:

While()

For our script, we want
it to end at the end of the file, which we defined by its length. So we say “so
long as the counter $i is less than the length ($length)of the file” this is accomplished with the –le (Less than)
operator:

While ($i -le $length)

When we append this to
the end of the script, and ensure that the variables are before it, it should
look like this:

$source = @(Get-Content source.txt)

$length = $source.length

$i = 0

Do{

If(($i%2) -eq 0){

Write-Host
$source[$i] "is odd"

}

if(($i%2) -eq 1){

Write-Host
$source[$i] "is even"

}

$i++

}

While ($i -le $length)

But Wait! The math is all wrong! If the counter has a
remainder of 0 it is even, yet I stated that it is even! This is intentional. Arrays start at 0 so they are offset by
one. So 0 is the first position, 1 is
the second position, so on and so forth.

In plain English what
we have done is this:

“Read this file, and
tell me if every line is either even, or odd.
Do this until the end of the file. ”

And there you have
it. Should you have any questions, or
even a better way to do this, do not hesitate to let me know. If you are as fast as me with a mouse, it
takes a second to +1, Like, Tweet, Share.

Nice post! Here is another way:

ReplyDelete$r = Get-Content .\test.txt

for($idx=0; $idx -lt $r.count; $idx+=2) {

$r[$idx]

}

Doug

http://dougfinke.com

Doug,

ReplyDeleteThank you for the comment! This is exactly why I post these DIY articles, as there is Always another way to do something. And BTW, I have referenced your book before for production scripts.

-Rob Stevens

Hi Rob,

ReplyDeletewhy not using this simple form:

Get-Content -path "Textfile" | where-object {($_.ReadCount % 2) -eq 0 }

Kind regards,

Andreas