Tuesday, August 04, 2009

“I found $x very bizarre while learning powershell”

Coming from most other directions, powershell is truly bizarre. I started this a few years ago when I started learning PowerShell because I suspected that I would not be able to remember why powershell is so non-intuitive.

Confusing: Verb-Object?

I can’t be the only programmer who finds the syntax backwards. In almost every other language I’ve worked with, you have an object (or module) and call a method on it.

new EvilService().CreateRandomEvilPlan()

You can do that in powershell, but it’s not the powershell way.

Add-EvilPlan

The paradigms will get confused in most code, as anything that doesn’t have a commandlet uses the standard paradigm. You can access normal .NET objects (or com objects)

$proxy = New-WebServiceProxy -URI $uri -Class "DSP" -Namespace "Daptiv"

$proxy.

Whoa … Functions, and everything else, can be treated like a file.

Get-Item -Path function:

new-item -path function: -name csrss -options readonly -value {get-process csrss}

Everything in the output of this powershell method can be treated like a file system:

get-psdrive

For example:

get-item env:C*

dir env:C*

dir variable:ps*

A lot of functionality in powershell is exposed through providers with consistent syntax, revolving around items. This is a bit mind-blowing at first: I work with functions, the registry and certificates just like files? Then, it becomes fairly powerful.

Piping objects? Think reduce, not pipes

Shell script authors know pipes, but these are typically text or byte pipes, not object pipelines. Object pipelines are cool because 1) it’s really easy to distinguish one object from the next. No worry about terminators. 2) You can act on those objects, walk graphs within the pipeline (it’s not always a good idea, though).

Functional programming languages has the concept of reduce. I am happiest thinking of pipelines in functional programming terms.

Yeah … slices and easy list types!

While experimenting with python for operational purposes, I found the list handling superbly powerful. Defining a list of servers to act on, tuples to quickly group data, all were great. Some of these things can also be done in powershell. The operations aren’t made as easy in real languages, for fear of nasty performance problems working with long lists.

See help_about_array. Highlights.

$webservers= "webapp1","webapp2", “webapp3”

or strongly typed:

[string[]] $webservers= "webapp1","webapp2", “webapp3”

Slice it to get a part (webapp1, webapp2)

$webservers [0..1] = "webapp1","webapp2", “webapp3”

Use the plus operator (+) to combine two arrays

$dbservers= “db1”,“db2”

$allservers=$webservers + $dbservers

Dictionaries are as easy as I hoped. See help about_hash_tables

$lookup = @{coffee="bitter";apple="sweet";peanut="crunchy";banana="sweet"}

With a surprising access mechanism -- not $lookup(“peanut”), but

$lookup.peanut

Sorting and filtering lists and dictionaries is simpler and more powerful than most languages, because it ties into the powershell object pipeline.

$lookup = @{coffee="bitter";apple="sweet";peanut="crunchy";banana="sweet"}
$lookup.getenumerator() | sort-object -property key
$lookup.getenumerator() | where-object {$_.Value -eq "sweet"}

One liners can be more than one line

In summary, here is one “line” of powershell:

$x=(@("Verb-Object semantics",
    "everything is a drive",
    "piping objects",
    "slices and lists",
    "powershell line continuation",
    "string interpolation") `
    | Where-Object {!$_.Contains("lists")}); $y=[String]::Join(",",$x); "I found $y bizzare truly bizzare while learning powershell."