Skip to content

Commit

Permalink
main
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Dec 4, 2024
1 parent d7651d1 commit 5a13b4d
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 13 deletions.
33 changes: 29 additions & 4 deletions docs/document/Powershell/docs/Language/Array.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

- `<arr> -eq <item>`: returns all items in `<arr>` equal to `<item>`.
- `<arr> -ne <item>`: returns all items in `<arr>` not equal to `<item>`.
- 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.
Expand All @@ -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<T>`.
Expand All @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions docs/document/Powershell/docs/Language/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 15 additions & 4 deletions docs/document/Powershell/docs/Language/HashTable.md
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -17,6 +20,7 @@ $foo = @{
Name = 'foo'
Age = 18
}
$foo = @{ Name = 'foo'; Age = 18 }
```

Expand All @@ -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]
Expand All @@ -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)
Expand All @@ -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
Expand Down
9 changes: 5 additions & 4 deletions docs/document/Powershell/docs/Language/PSCustomObject.md
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -13,7 +14,7 @@ $john = [PSCustomObject] @{
}
```

### From a HashTable
### From HashTable

You can explicitly convert a HashTable to PSCustomObject

Expand All @@ -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
Expand Down
14 changes: 13 additions & 1 deletion docs/document/Powershell/docs/Language/Script Block.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -14,6 +16,13 @@ $func = {
}
```

### From String

```ps1
$script = [scriptblock]::Create('echo hello')
& $script # hello
```

## Invoke a Script Block

```ps1
Expand All @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions docs/document/Powershell/docs/Language/String.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 '^(?<FirstName>\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#`.
Expand Down

0 comments on commit 5a13b4d

Please sign in to comment.