diff --git a/docs/document/Powershell/docs/Language/Array.md b/docs/document/Powershell/docs/Language/Array.md index 274fc288..d95f4a5e 100644 --- a/docs/document/Powershell/docs/Language/Array.md +++ b/docs/document/Powershell/docs/Language/Array.md @@ -154,6 +154,28 @@ To substract a collection from another collection, you can certainly use `LINQ` @(1,2,3) | where { @(1, 2) -notcontains $_ } # 3 ``` +## Equality Checking + +Collections behave differently in Powershell on equality checking, they're not based on reference but the contained items. + +- ` -eq `: returns all items in `` equal to ``. +- ` -ne `: returns all items in `` not equal to ``. +- always returns `object[]` even for single result or no result. + +```ps1 +1,1,2,3 -eq 1 # 1,1 +'a','b','c' -ne 'a' # 'b', 'c' + +# the whole item is an array so no result is returned. +1,1,2,3 -eq 1,2 # empty array +``` + +> [!TIP] +> You can use `-ne` to exclude single item from a collection. + +> [!NOTE] +> To do reference checking, use `[object]::ReferenceEquals`. + ## Null Checking Checking null for collections is a quirk in PowerShell, `$arr -eq $null` checks all items instead of the whole array. @@ -164,10 +186,11 @@ $arr = 1,2,3 $arr -eq $null # empty array $null -eq $arr # False, the result we expected # [!code highlight] - -if ($arr) { 'array is not null and not empty' } # check both empty and null ``` +> [!TIP] +> Always leave array as the right operand on null checking. + ## To List PowerShell allows direct casting a array to an `ArrayList` or generic `List`. @@ -184,18 +207,20 @@ using namespace System.Collections.Generic Keyword operators has special functionalities on collections. `-match`, `-notmatch`, `-replace`, `-split` handles for all items in the left operand collection, the result is always an array. -If the item is not a string, Powershell evaluates it to string by certain strategy. ```ps1 # Returns items that matches the regex @('John', 'Jane', 'Janet') -match 'Jane' # Jane, Janet. -(gci -file) -match '.*txt$' # FileInfo[], files with FullName matches to the pattern +(gci -file) -match '.*txt$' # FileInfo with FullName matches to the pattern (@('John', 'Jane', 'Janet') -notmatch 'Jane') -is [Array] # True, only John matches and still an array. @('John', 'Jane', 'Janet') -replace 'J','K' # Kohn Kane Kanet '1,2,3','1,2,3' -split ',' # 1 2 3 1 2 3, strings ``` +> [!NOTE] +> If current item for `-match` or `-notmatch` is not a string, Powershell evaluates it to string by certain strategy. + ## Multi-Dim Array You'll have to create Multi-Dim array from .NET type constructor only. diff --git a/docs/document/Powershell/docs/Language/Function.md b/docs/document/Powershell/docs/Language/Function.md index 45a67fa0..b6137847 100644 --- a/docs/document/Powershell/docs/Language/Function.md +++ b/docs/document/Powershell/docs/Language/Function.md @@ -204,6 +204,27 @@ param ( ) ``` +### Pass By Reference + +Parameter passed by reference is implemented by a wrapper `System.Management.Automation.PSReference`. +Value types are passed by value by default, the pass as reference, mark the parameter with `[ref]`. +Casting to `[ref]` generates a new wrapper containing the value. + +```ps1 +function Foo { + param ([ref][int]$foo) # [!code highlight] + $foo.Value = 250 + $foo.Value +} + +$bar = 1 +Foo ([ref]$bar) +$bar # 250 # [!code highlight] +``` + +> [!NOTE] +> `[ref]` can only be marked before type annotation. + ## Named Blocks In a simple function where there's only one series of parameters being taken, we don't have to use any complex logic. diff --git a/docs/document/Powershell/docs/Language/HashTable.md b/docs/document/Powershell/docs/Language/HashTable.md index 668e502c..56d4207a 100644 --- a/docs/document/Powershell/docs/Language/HashTable.md +++ b/docs/document/Powershell/docs/Language/HashTable.md @@ -1,12 +1,15 @@ # HashTable -HashTable is a dynamicly typed data structure in PowerShell, it implements `IDictionary` but is wrapped with the extended types system. -It's the native type and is unique to PowerShell itself. +HashTable is essentially `System.Collections.HashTable`, the non-generic version of `Dictionary<,>`. ```ps1 @{} -is [System.Collections.IDictionary] # True +@{} -is [System.Collections.HashTable] # True ``` +> [!TIP] +> HashTable serves as more like a dictionary with syntax sugar, if you want it to be more like object literal, use `[pscustomobject]`. + ## Creation PowerShell has builtin syntax for creating a HashTable. @@ -17,6 +20,7 @@ $foo = @{ Name = 'foo' Age = 18 } + $foo = @{ Name = 'foo'; Age = 18 } ``` @@ -29,13 +33,13 @@ $foo = @{ Name = 'foo'; Age = 18 } C = 'C' B = 'B' A = 'A' -}).Keys # C B A +}).Keys # C B A # [!code highlight] @{ C = 'C' B = 'B' A = 'A' -}.Keys # B C A +}.Keys # B C A # [!code highlight] ``` > [!NOTE] @@ -47,6 +51,7 @@ $foo = @{ Name = 'foo'; Age = 18 } ## Access Values You can access value of one or more keys by indexer. + ```ps1 $foo['Name'] # foo $foo['Name', 'Age'] # @('foo', 18) @@ -56,11 +61,17 @@ $foo['Name', 'Age'] # @('foo', 18) ```ps1 $foo.Name # foo +$foo.'Name' +$name = 'name' +$foo.$name ``` > [!TIP] > Always use indexer to access value of a HashTable. `.` will prefer Extended Property that might be unexpected. +> [!NOTE] +> Key in HashTable can be any type. So if the key is not a singular type, you'll have to extract the key from `Keys` first and then access the value by the key. + ## Merging ```ps1 diff --git a/docs/document/Powershell/docs/Language/PSCustomObject.md b/docs/document/Powershell/docs/Language/PSCustomObject.md index 09b662d1..2b4318dd 100644 --- a/docs/document/Powershell/docs/Language/PSCustomObject.md +++ b/docs/document/Powershell/docs/Language/PSCustomObject.md @@ -1,8 +1,9 @@ # PSCustomObject -**PSCustomObject** is similar to object literal that can even have custom methods. +Differ from HashTable, `[PSCustomObject]` is a representation for object literal. +It -## Create a PSCustomObject +## Creation PSCustomObject borrows the syntax from HashTable with a casting. @@ -13,7 +14,7 @@ $john = [PSCustomObject] @{ } ``` -### From a HashTable +### From HashTable You can explicitly convert a HashTable to PSCustomObject @@ -25,7 +26,7 @@ $table = @{ $obj = [PSCustomObject]$table # [!code highlight] ``` -Or use `New-Object` +Or use `New-Object`, but this might be slower. ```ps1 $obj = New-Object -TypeName PSObject -Property $table diff --git a/docs/document/Powershell/docs/Language/Script Block.md b/docs/document/Powershell/docs/Language/Script Block.md index a32c5ae4..42602965 100644 --- a/docs/document/Powershell/docs/Language/Script Block.md +++ b/docs/document/Powershell/docs/Language/Script Block.md @@ -3,6 +3,8 @@ **Script Block** is a special object in powerhsell, it looks like a syntax that creates a new scope in the flow, but itself can be stored in a variable. So it's more like a anonymous function, you may call it as lambda expression. +## Creation + ```ps1 $action = { echo 'hello from script block' @@ -14,6 +16,13 @@ $func = { } ``` +### From String + +```ps1 +$script = [scriptblock]::Create('echo hello') +& $script # hello +``` + ## Invoke a Script Block ```ps1 @@ -24,11 +33,14 @@ $func = { & { param($a, $b) $a, $b } 'a' 'b' # a # b + +# store result to variable +$arr = & { param($a, $b) $a, $b } 'a' 'b' ``` ## Script Block as Lambda -As a replacement for lambda expression, Script Block is being used to work with LINQ api. +As a replacement for lambda expression. ```ps1 $arr = @(1, 2, 3, 5) diff --git a/docs/document/Powershell/docs/Language/String.md b/docs/document/Powershell/docs/Language/String.md index ed815bd5..23e95c05 100644 --- a/docs/document/Powershell/docs/Language/String.md +++ b/docs/document/Powershell/docs/Language/String.md @@ -116,6 +116,17 @@ Exception will be raised if conversion failed. 'Janet is a girl' -replace '^Janet', 'Jane' ``` +All previous matches and captured groups can be accessed in `$matches` builtin variable. +`$matches` is a HashTable, you can access named capture group by group name and use index for unamed group. + +```ps1 +if ('John Smith' -match '^(?\b\w+\b) (\b\w+\b)$') { + $matches.FirstName # John + $matches[0] # John Smith + $matches[1] # Smith +} +``` + ## Format String Template string syntax is the same as `C#`.