Skip to content

Commit

Permalink
grrr
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpchen committed Nov 17, 2024
1 parent b9a35ce commit 3c4b7aa
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 21 deletions.
10 changes: 10 additions & 0 deletions docs/document/Powershell/docs/1.Overview.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Overview

- Integrated with `.NET`
Reuse almost any type in `.NET`.
- Dynamic typing
Powershell adds extra attribute and properties on dotnet types to enhance experience.
- Case insensitive
All language syntax, pattern syntax and even strings are case-insensitive.
(There's exception for file system on non-Windows platform)
- Everything is object, more than plain text in shell.
Powershell formats the object value as a table if the object is not a primitive type.
For primitive type, `Tostring()` will be used instead.
- Always handle both array and singular object.
A powershell cmdlet always accepts an array or an single object as input parameter.
And returns the result as an array or an object too.
4 changes: 2 additions & 2 deletions docs/document/Powershell/docs/File System/1.Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

**FileSystem** is a builtin **PSProvider** in Powershell.

FileSystem can have one or more **PSDrive** depends on the system.
FileSystem can have one or more **PSDrive** depending on the system.

In windows, drives can be `C:`, `D:` and so on. In linux they can be some mount points.

This is introduces how to manipulate file system objects with item-related cmdlet.
This section introduces how to manipulate file system objects with item-related cmdlet.
5 changes: 5 additions & 0 deletions docs/document/Powershell/docs/Language/Collection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Collection

## Array

## HashTable
35 changes: 35 additions & 0 deletions docs/document/Powershell/docs/Language/Function.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
# Function

## Return

Powershell allows implicit return, and multiple implicit returns.

> [!NOTE]
> Implicit returns are auto-collected as an array or single value.
> And it does not print out anything.
```ps1
[int] function Sum {
param([int]$l, [int]$r)
$l + $r # implicit return # [!code highlight]
}
# You won't need to declare an array and append it on each loop!
# they're collected automatically as they're implicit returns
function Foo {
for($i = 0; $i -lt 10; $i = $i + 1) {
$i
}
}
(Foo).GetType().Name # object[] # [!code highlight]
```

Explicit return is surely supported, but more like a necessity to exit inside a flow.

```ps1
[int] function Sum {
param([int]$l, [int]$r)
return $l + $r # explicit return # [!code highlight]
$r + $l # not reachable # [!code warning]
}
```

## Parameter

Parameters are wrapped inside a function block with `param(...)`
Expand Down
36 changes: 36 additions & 0 deletions docs/document/Powershell/docs/Language/Invocation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Invocation

> [!CAUTION]
> Always be careful to run an external script or input script content.
## Call Operator

Call operator `&` can be used for invoking one of the following:

- Command without any option.
- A `.ps1` script file
- Script block

**`&` is awared of the context of current session, it does not start a new process.**

It's more like a system execution

```ps1
& 'gps'
& 'gps pwsh' # extra option not allowed # [!code error]
& 'gps' pwsh # pass option after command name instead # [!code ++]
& 'gps' -Name pwsh # pass option after command name instead # [!code ++]
& 'path/to/script.ps1' # may add some option... # [!code highlight]
& { param($a, $b) $a, $b } 1, 2
```

## Invoke-Expression

`Invoke-Expression` used for executing any script content represented as a string.

```ps1
Invoke-Expression 'gps pwsh'
'gps pwsh' | iex
```
45 changes: 45 additions & 0 deletions docs/document/Powershell/docs/Language/PSCustomObject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# PSCustomObject

**PSCustomObject** is similar to object literal that can even have custom methods.

## Create a PSCustomObject

PSCustomObject borrows the syntax from HashTable with a casting.

```ps1
$john = [PSCustomObject] @{
Name = 'John Smith'
Age = 18
}
```

### From a HashTable

You can explicitly convert a HashTable to PSCustomObject

```ps1
$table = @{
Foo = 'foo'
}
$obj = [PSCustomObject]$table # [!code highlight]
```

Or use `New-Object`

```ps1
$obj = New-Object -TypeName PSObject -Property $table
```

## Copy a PSCustomObject

- Shallow copy

```ps1
$john = [PSCustomObject] @{
Name = 'John Smith'
Age = 18
}
$smith = $john.PSObject.Copy()
```
36 changes: 36 additions & 0 deletions docs/document/Powershell/docs/Language/Script Block.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Script Block

**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.

```ps1
$action = {
echo 'hello from script block'
}
$func = {
param($foo, $bar)
return "$foo$bar"
}
```

## Invoke a Script Block

```ps1
& { 1, 2 }
# 1
# 2
& { param($a, $b) $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.

```ps1
$arr = @(1, 2, 3, 5)
$arr.Where({ $_ -lt 4 })
```
17 changes: 0 additions & 17 deletions docs/document/Powershell/docs/Modulization/Modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,3 @@ Search module to be installed in registered repositories.
Find-Module <pattern>
```

## Custom Module Path

Powershell automatically scans modules at certain locations.
Inspect existing module path by:

:::code-group
```ps1[Windows]
$env:PSModulePath -split ';' # windows
```
```ps1[Linux/Mac]
$env:PSModulePath -split ':' # linux/mac
```
:::

```ps1
$env:PSModulePath += [IO.Path]::PathSeparator + '<path>'
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Powershell is a Object-Oriented shell language, so inspection and manipulation o

This section focuses on how to work with objects, including:

- LINQ like transformation over objects.
- LINQ like transformation over objects.(including usage of `.NET` LINQ in Powershell)
- Object comparison.
- Serialization and Deserialization.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Compare Objects

## Overview

> [!TIP]
> Use `diff` or `compare` alias for `Compare-Object`
Expand Down Expand Up @@ -46,4 +48,4 @@ diff @('abc', 'dfg') @('fg', 'abc') -Property Length # compare on string.Length
- `ToString()` and compare on string

> [!TIP]
> If the object to be compared doesn't implement `IComparable`, you should use `-Property`.
> If the object to be compared doesn't implement `IComparable`, you should use `-Property` unless it's a primitive type.
110 changes: 110 additions & 0 deletions docs/document/Powershell/docs/Object Manipulation/Select.md
Original file line number Diff line number Diff line change
@@ -1 +1,111 @@
# Select

`Select-Object` is a combination of `Select`, `Take`, `TakeLast` in dotnet LINQ.
It can be appiled on singular object and any collection.

> [!TIP]
> Use `select` alias for `Select-Object`.
## Select as an Object

`Select-Object` wraps selected properties as an `PSCustomObject`

```ps1
gps | Select-Object -Property Name # gets an object[] instead of string[]
(gps | select Name -First).GetType().Name # PSCustomObject
```

You can select multiple properties:

```console
$ gps | select Name, Id -First 1 | gm

TypeName: Selected.System.Diagnostics.Process

Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Id NoteProperty int Id=12588
Name NoteProperty string Name=ABDownloadManager
```

### Nested Property and Custom Property

`-Property` accepts a **Script Block** to calculate the **nested** property you'd like to select.

```console
$ gps | select Name, { $_.StartTime.DayOfWeek } -First 1

Name $_.StartTime.DayOfWeek
---- ------------------------
ABDownloadManager Thursday
```

You can even define a custom calculation with a HashTable shaped as:
- `lable: string`: name of the property
- `expression: ScriptBlock`: an procedure returns the calculated property value.

```console
$ gci -File | select Name, @{ label = 'Size(KB)'; expression = { $_.Length / 1KB } }

Name Size(KB)
---- --------
.gitignore 0.01
dotfiles.ps1 1.69
flake.lock 1.64
flake.nix 1.02
home.nix 0.63
install.ps1 1.49
make_vs.ps1 2.06
README.md 0.85
```

## Select Value Only

To select value of a property instead of being wrapped as an object, use `-ExpandProperty`.
The return type is still an `object[]` since there's no generic resolution on Powershell.
But each memeber should be string indeed in the following snippet.

```ps1
gps | select -ExpandProperty Name
(gps | select -ExpandProperty Name).GetType().Name # object[]
(gps | select -ExpandProperty Name -First 1) -is [string] # True
```

> [!NOTE]
> `-ExpandProperty` can only take one property.
## Take a Count

`Select-Object` can also take specific count of items from a collection, from start or end.

```ps1
gps | select -First 5
gps | select -Last 5
```

## Skip a Count

```ps1
gps | select -Skip 5
gps | select -SkipLast 5
```

## Cherry Pick

```ps1
$dir = ls -Directory
$dir | select -Index 1, ($dir.Length - 1) # Pick first and last item
```

## Distinct

```ps1
# might have duplicated entries since file extensions should ignore casing.
ls | select Extension -Unique
# list all extensions appeared in current directory
ls | select Extension -Unique -CaseInsensitive
```

0 comments on commit 3c4b7aa

Please sign in to comment.