Two of the oft-touted features of PowerShell are the idea that you can pipe objects from one cmdlet to the next and PSDrives.
In bash or cmd, when you pipe the output of one command to another, it sends the text that is printed to STDOUT to the STDIN of the next process. This means that there are a lot of commands just to help you massage and manipulate the text on the screen so that you can get the right output.
In PowerShell, the objects themselves are passed from one cmdlet to the next. Here's an example:
If I type
cd HKLM:
I am now at the root of the HKEY_LOCAL_MACHINE, since HKLM: is a PSDrive set up so that I can navigate the registry just like a drive on my computer. You can see the whole list of PSDrives by typing in "psdrive" at the command prompt.
If I type
dir
I get this:
PS HKLM:\> dir
Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE
SKC VC Name Property
--- -- ---- --------
7 3 COMPONENTS {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime}
4 0 HARDWARE {}
1 0 SAM {}
042 0 Schema {}
15 0 SOFTWARE {}
9 0 SYSTEM {}
(I'm on Vista running in non-administrator mode, so that's why I don't have access to the schema)
This appears to be sorted by the Name attribute, but let's say I don't want to sort on the Name attribute, I'm more interested in the SKC attribute (whatever that is):
PS HKLM:\> dir | sort SKC
Hive: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE
SKC VC Name Property
--- -- ---- --------
042 0 Schema {}
15 0 SOFTWARE {}
9 0 SYSTEM {}
7 3 COMPONENTS {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime}
4 0 HARDWARE {}
1 0 SAM {}
I have the data that I want, but I want to display it differently:
PS HKLM:\> dir | sort SKC | format-list
Get-ChildItem : Requested registry access is not allowed.
At line:1 char:4
+ dir <<<< | sort SKC | format-list
Name : Schema
ValueCount : 0
Property : {}
SubKeyCount : 1042
Name : SOFTWARE
ValueCount : 0
Property : {}
SubKeyCount : 15
Name : SYSTEM
ValueCount : 0
Property : {}
SubKeyCount : 9
Name : COMPONENTS
ValueCount : 3
Property : {StoreFormatVersion, StoreArchitecture, PublisherPolicyChangeTime}
SubKeyCount : 7
Name : HARDWARE
ValueCount : 0
Property : {}
SubKeyCount : 4
Name : SAM
ValueCount : 0
Property : {}
SubKeyCount : 1
If you want to pipe a non-cmdlet, then it will send the text output to the pipe just like you're used to, but you can manipulate it easily in PowerShell. $_ is a special "default" variable for the input, similar to $_ in Perl. This lets you do things like this:
cat xunlei.txt | where {$_ -match '\sBEJ-73716507\s'}
cat xunlei.txt | where {$_ -match '\sBEJ-73716507\s'} | foreach {echo("Found it!!! " + $_)}
The first command pipes the output of cat (cat and echo are aliases for Write-Output) to the where statement that filters out everything that doesn't match the regular expression, kind of like grep. The second command does the same, but then prepends the string "Found it!!! " to the beginning of each line before printing it to the screen.
NOTE: When using the + operator to concatenate strings it is usually necessary to put parentheses around the whole string. Otherwise the + operator uses some funky overloaded function and it won't do what you expect.
No comments:
Post a Comment