Summary: Microsoft Scripting Guy, Ed Wilson, teaches you how to handle arrays in Windows PowerShell.
Hey, Scripting Guy! One of the things I do not understand is arrays. I mean, I really do not get it at all. In VBScript, it seemed like I always tripped up on arrays. In Windows PowerShell, it seems that no one ever talks about arrays. I am not claiming that I was ever a great VBScript person, but at least I got to the point where I could sort of read and understand a script that I was copying from the Script Center. In fact, at work, everyone will tell you that I am actually the scripting guy (no offence). In VBScript there were tools that I could use (like isarray) that would tell me if I had an array—but in Windows PowerShell, I never see anything of the sort. What gives?
—JF
Hello JF,
Microsoft Scripting Guy, Ed Wilson, is here. I do not mind if you are considered the scripting guy at your work—in fact, I am flattered. I think scripting guy should be a job title just like network administrator or system analyst. After getting your email at scripter@microsoft.com, I went back through the blogs I have written over the last three years or so, and sure enough, I have not written a lot about arrays. I have one blog called Using PowerShell Get-Member to Explore the .NET Framework, and I have a few other posts that are a bit more advanced, but it seems to be that I have not gotten down and focused on using Windows PowerShell to work with arrays. Thank you for calling this to my attention, and I intend to rectify this issue immediately with Array Week.
What is an array?
An array is a way of storing data that permits more than one item to be stored in the variable or in the field. For example, suppose I want to store a single number in a variable, all I need to do is to use a straightforward value assignment. This command appears here.
$a = 1
But what if I need to store two numbers in the same variable? In this case, I use a comma to separate the values that I want to store. This is illustrated here.
$b = 2,3
There is no need to have a space between the comma and the next number when storing values in an array. In fact, Windows PowerShell is extremely flexible when it comes to spaces around the comma. All of the following commands work and create an array containing two elements.
$c = 4 , 5
$d = 6, 7
$e = 8 ,9
These commands and their associated output are shown in the following image.
Elements, indexes, and values, Oh My!
Each item that is stored in an array is an element. When working with an array, we need a way to address each item that is contained in array. To do this, we use index numbers. The index numbers reference each element that is stored in an array. The thing that gets a bit confusing is that in Windows PowerShell, arrays always begin with zero. Therefore, the first element in an array is indexed by 0. You can also refer to that as element zero. The table that follows illustrates these concepts.
Element number |
1 |
2 |
3 |
4 |
Index number |
0 |
1 |
2 |
3 |
Value in the array |
A |
B |
C |
D |
To create an array with four elements, I assign a value to each element by separating each value with a comma. In the following code, I assign the letters A, B, C, and D to an array named ARRAY. Windows PowerShell stores the array in a variable, and therefore, referencing the array requires a dollar sign in front of the variable. To see the data that is stored in an array, I can simply call the variable, and each element of the array appears on its own line in the Windows PowerShell console. The commands to create an array and view its contents are shown here.
PS C:\> $ARRAY = "A","B","C","D"
PS C:\> $ARRAY
A
B
C
D
In other languages, it is possible to create an array that is zero-based or one-based. Having a one-based array avoids the confusion of having element 0 addressed by index 1, but it introduces another type of confusion—is the array I am working on zero-based or one-based? In any language where the capability to create an array that is zero-based or one-based exists, it is essential to have the capability to discover the lower boundary of array. To discover the lower boundary of an array, use the GetLowerBound method. The use of the GetLowerBound method is shown here.
PS C:\> $ARRAY.GetLowerBound(0)
0
Of course, in Windows PowerShell the lower boundary of an array is zero; and therefore, the command is not useful. What is useful is the GetUpperBound method, because it indicates how many items the array contains. The use of the GetUpperBound method is shown here.
PS C:\> $ARRAY.GetUpperBound(0)
3
When I have a good idea of the dimensions (the lower boundary and the upper boundary) of my array, I can use square brackets to retrieve individual elements from the array. The technique of retrieving individual elements from an array is called indexing. Therefore, I use square brackets to index into my array and retrieve the individual elements. To obtain the first element in the array, I use index zero as shown here.
PS C:\> $ARRAY[0]
A
If I want to obtain the third item (element) in my array, I use index two (because the array is zero-based, I always add 1). This command is shown here.
PS C:\> $ARRAY[2]
C
The commands to create an array, obtain its boundaries, and index it into the first and third elements of the array are shown here with the associated output.
In other languages, it is common to use the for statement to walk through an array. This technique also works in Windows PowerShell. The steps to do are:
- Use the for statement.
- Use the GetLowerBound method to obtain the lower boundary of the array.
- Use the GetLowerBound method to obtain the upper boundary of the array.
- Use a counter variable to keep track of the element numbers.
- Use the + + operator to increment the counter variable.
- Use the counter variable to index directly into the array.
The code to use the for statement to walk through the $ARRAY array is shown here.
for($i = $ARRAY.GetLowerBound(0); $i -le $array.GetUpperBound(0); $i++) {$ARRAY[$i]}
Because the lower boundary of a Windows PowerShell array is always zero, the command can be shortened a bit by using 0 in place of the GetLowerBound command. The simplified version of the command is shown here.
for($i = 0; $i -le $array.GetUpperBound(0); $i++) {$ARRAY[$i]}
Two properties describe how many elements an array contains: the Length property and the Count property. The thing to keep in mind is that both the Length and the Count properties are one-based—that is, the first element is 1. Therefore, if you are using the for technique to walk through an array, it is necessary to subtract 1 from the Length property or the Count property. The following two commands illustrate these techniques.
for($i = 0; $i -le $array.count -1; $i++) {$ARRAY[$i]}
for($i = 0; $i -le $array.length -1; $i++) {$ARRAY[$i]}
The command to use the for statement with the GetLowerBound and the GetUpperBound methods, in addition to the other versions of the command, are shown in the following image.
Send the array through the pipeline
One of the really powerful aspects of Windows PowerShell is that it automatically handles arrays; therefore, things like lower boundaries, upper boundaries, elements, and index numbers are avoidable. For example, by using the pipeline and the Foreach-Object cmdlet, all the complexity disappears. The steps to use the Foreach-Object cmdlet to address elements in an array are:
- Pipe the array to the Foreach-Object cmdlet.
- Inside the script block that is associated with the Foreach-Object cmdlet, use the $_ automatic variable to reference each element of the array.
The following command illustrates the pipeline technique to access elements in an array.
$ARRAY | foreach-object { $_ }
If I decide to use the % alias for the Foreach-Object cmdlet, the command becomes even shorter. The following command illustrates this technique.
$ARRAY | % { $_ }
The following image illustrates using the pipeline technique to access elements in an array, along with the associated output from the commands.
JF, that is all there is for part one. Array Week will continue tomorrow when I continue talking about creating and manipulating arrays.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy