Wednesday, July 1, 2015

Beginner's Guide - Working with lists (part 1)

One of the great advantages to using Powershell as an administration method in Windows AD environments is its ability to work with many computers or user accounts or files at once.  One of the key concepts is understanding lists.  The basic assumption I make here is that you know how variables are assigned and created.  Lets cover some of the many ways to be effective with lists.

If you'd like to skip ahead:
Part 2: working with object arrays
Part 3: building custom object arrays from scratch
Part 4: manipulating objection arrays and custom selects

Computer Science 101 - Arrays

The first thing you must understand is that there are two types of "lists" in Powershell: hash tables and arrays.  Hash tables are lists of name + value pairs. Notice how they aren't ordered; this is true for all hash tables. Arrays are always ordered.

PS C:\> $HT = @{}        #Declares a new empty hash table
PS C:\> $HT["head"]="hat"
PS C:\> $HT.Add("chest","shirt")
PS C:\> $HT["legs"]="pants"
PS C:\> $HT.Add("feet","shoes")
PS C:\> Write-Output $HT

Name                           Value
----                           -----
chest                          shirt
head                           hat
legs                           pants
feet                           shoes


PS C:\> $HT.GetType()   #This handy method tells you what kind of data your variable is.

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Hashtable                                System.Object


We won't spend much time on hash tables as they have very important purposes, but for the direction of this tutorial, we'll be focusing on arrays.  The key takeaway with hash tables is that they have only two "columns" of data, Name and Value.  An array is a collection of objects.  An object in Powershell can be of any data type.  Here's some information on data types in Powershell.

In addition to the basic data types, objects can be any combination of data types.  Think about an excel spreadsheet with many columns of data, each different.  In Powershell, that would be an array of objects, where the row is the object record or item.  The whole spreadsheet has many records.  The columns symbolize the different fields (called properties in Powershell) and each one can be a different type.

For simplicity sake, lets start with an array of strings.  This is probably what you think of when you hear "list".  Notice that they don't have any column headings when you do a Write-Output on them.  Here are a few ways to make lists:

PS C:\> notepad servers.txt         #Enter one server per line
PS C:\> $stringarray = Get-Content .\servers.txt   #Reads in the file and creates a single array, string object per line.

PS C:\> Write-Output $stringarray
Server1
Server2
Server3
Server4
NotAServer


PS C:\> $stringarray.GetType()        #technically, all arrays are just object arrays

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array


PS C:\>


PS C:\> #This is NOT an example of an array, it's simple a multi-line string denoted by the special end markers @"  and  "@
PS C:\> $notAstringArray = @"
>>> lets
>>> try
>>> this
>>> out
>>> "@
PS C:\> $notAstringArray.GetType()    #This is just a string, not an array

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS C:\>

PS C:\> $AlsoStringArray = @()           #Definitng an empty array
PS C:\> $AlsoStringArray += "First"      #The += operator basically means append this to my array
PS C:\> $AlsoStringArray += "Second"
PS C:\> $AlsoStringArray += "Third"
PS C:\> Write-Output $AlsoStringArray
First
Second
Third


String Array indexing

So now we have some basic concepts down, lets look a bit more at string arrays specifically.  You can use the built in parameter ".count" which lets you see how many items are in the array.  Also, you can select any record in the array by addressing it's index number.  Arrays are ordered with an index starting at 0 and going up to the .count - 1.

PS C:\> $AnotherStringArray = @("server10","server20","server30")  #another way to make a string array

PS C:\> $AnotherStringArray.count           #Shows number of records in array
3

PS C:\> $AnotherStringArray[0]              #gets the first item in the array
server10

PS C:\> $AnotherStringArray[1]
server20

PS C:\> $AnotherStringArray[2]
server30

PS C:\> $AnotherStringArray[3]              #gets the 4th item, which there is none, so $null is returned (nothing)

PS C:\> $AnotherStringArray[-1]             #special index for getting the last item
server30

PS C:\> $AnotherStringArray[-2]             #gets the second to last item
server20

PS C:\> $AnotherStringArray[0].GetType()    #If we do a .GetType() on the actual record, it's a data type of string, not array

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS C:\>



More String Array fun

Once you have your String Array, you can do fun things like selecting parts of it, and sorting it alphabetically (or reverse).  You can also select records which contain (or don't contain) certain characters, are of a minimum (or maximum) length, and of course write it out to a file.

PS C:\> $servers = Get-Content C:\users\bryan.VINES\servers.txt

PS C:\> $servers | select -first 3 -skip 1    #returns the first 3 items in the list after skipping 1
Server2
Server3
Server4

PS C:\> $servers | select -Last 2             #returns the last 2 items
Server4
NotAServer

PS C:\> $servers | sort -Descending
Server4
Server3
Server2
Server1
NotAServer

PS C:\> $servers | Where-Object{$_ -like "server*"}  #returns only items that start with server (non case sensitive)
Server1
Server2
Server3
Server4

PS C:\> $servers | Where-Object{$_ -like "*S*2*"}   #returns the items that have the letter S and then 2 in order in the them
Server2

PS C:\> $servers | Set-Content C:\outservers.txt -Verbose     #writes the string array to a text file.
VERBOSE: Performing the operation "Set Content" on target "Path: C:\outservers.txt".


Well, that's all for now.  In part 2, we'll look at other object arrays.

3 comments:

Abhay Kumar said...

Really a quick guide to powershell array and hash tables.
Thanks for sharing !!!!

Can u brief a bit on creating the custom tables too.

Bryan said...

Part 2 will be all about custom arrays (tables). It's worth dedicating an entire post to it since it's not a simple subject.

Anonymous said...

Very good tutorial for PowerShell beginners ��