Private/Wissen/B_Basic/B15_Operatoren.ps1

<#
 
# Operatoren
 
Die Operatoren der PowerShell
 
- **Hashtags** Operator Arithmetic Assignment Logical Comparison Type Split Join Zuweisung math logisch type
 
- **Version** 2020.05.24
 
#>


# ! Die Operatoren beginnen i.d.R. mit einem Bindestrich - oder sind besondere alleinstehende Zeichen wie . + - & etc.. Die Bindestrich-Operatoren dürfen nicht mit Switch-Parametern verwechselt werden: Where-Object 1 -EQ 1 <# vs. #> -1 -eq 1

# READ Weiterführende und Nachschlage-Informationen:

Get-Help -Name 'about_Operators'           -ShowWindow # READ Übersicht aller Operatoren
Get-Help -Name 'about_Operator_Precedence' -ShowWindow # READ Operator-Vorrangregeln

#region Arithmetische Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Arithmetic_Operators' -ShowWindow

1 + 1
9 - 1
-10
2 * 10
10 / 2
9 % 2 # ! Module (Der Rest einer Division)
15 -shl 1 # ! Shift left um X Bits
15 -shr 1 # ! Shift right um X Bits

#endregion

#region Zuweisungs-Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Assignment_Operators' -ShowWindow

$zahl=1   # Start: 1
$zahl++   # $zahl = $zahl + 1
$zahl--   # $zahl = $zahl - 1
$zahl+=2  # $zahl = $zahl + 2
$zahl-=3  # $zahl = $zahl - 3
$zahl++   # $zahl = $zahl + 1
$zahl     # Ergebnis: 1
$zahl=-10
$zahl     # Ergebnis: -10

# ! += bei Arrays

$varA = (Get-Process)[0]
$varA += (Get-Process)[1] # ! FEHLER Process-Objekte können nicht addiert werden
# vs.
$varB = @()               # Erzeugt ein leeres Array ...
$varB += (Get-Process)[0] # ... und fügt diesem ein Process-Objekt hinzu.
$varB += (Get-Process)[1] # ... und fügt diesem ein Process-Objekt hinzu.

# ! Wenn eine Zuweisung in Klammern gesetzt wird, wird der Wert der Variablen zugewiesen und der Wert wird ebenfalls ausgegeben, sodass ein nachgeschalteter Befehl ihn abrufen kann.

# Einfache zuweisung:
$Path1 = "$env:WinDir\explorer.exe"

# Eine Zuweisung inkl. Output:
($Path2 = "$env:WinDir\explorer.exe")

#endregion

#region Logische Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Logical_Operators' -ShowWindow

$true -and $true  # * = Wahr
$true -and $false # ! = Falsch
$true -or  $false # * = Wahr
$true -or  $true  # * = Wahr
$true -xor $true  # ! = Falsch

# ! Negieren (-not, !):

-not $true -and $true
# ODER:
!$true -and $true

# ! Klammern und Vorrangregeln (-and -or -xor):

($PSCulture -eq 'de-DE') -and ($Host.CurrentUICulture -eq 'de-DE')

($true -or $true) -xor ($true -and $true) # ! = Falsch, weil:
(      $true    ) -xor (      $true     ) # 1.
(                 $false                ) # 3.

 $true  -or $true  -xor  $true -and $true  # ! = Falsch, weil:
 $true  -or $true  -xor ($true -and $true) # 1.
 $true  -or $true  -xor        $true       # 2.
($true  -or $true) -xor        $true       # 3.
        $true      -xor        $true       # 4.
                   $false                  # 5.

# ! Bitweise Operatoren:

# -band, -bor, -bxor

#endregion

#region Vergleichs-Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Comparison_Operators' -ShowWindow
# ÜBERSICHT: lt le eq ne ge gt in notin contains notcontains like notlike match notmatch replace

# ! Gross-/Kleinschreibung berücksichtigen (Case-sensitive / case-Insensitive):

'Köln'                       -eq        'köln' # * = Wahr
'Köln'                       -ceq       'köln' # ! = Falsch
'Köln'                       -ieq       'köln' # * = Wahr (ieq IST ceq MIT eq)

# ! ACHTUNG - Sollten die Typen nicht kompatibel sein, findet ein implizites Konvertieren zum führenden Typen statt:

'010' -eq  010  # ! = Falsch
 010  -eq '010' # * = Wahr

# ! -like (Einfacher Mustervergleich):

# ? Keinmal bis n-mal => *
# ? Genau einmal => ?
# ? Nur a g oder h => [agh]
# ? Nur a bis h => [a-h]
# ? Alle Ziffern => [0-9]

'MeetingReport_20200501.docx' -like 'MeetingReport_????????.docx' # * = Wahr

# ! -match (Komplexe Musterprüfung mittels Reguläre Ausdrücke):

# READ https://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck

'MeetingReport_20200501.docx' -imatch '^MeetingReport_[0-9]{8,8}\.docx$' # * = Wahr

"info@attilakrick.com" -match "^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$" # * = Wahr

# ! Array-Vergleichsoperatoren:

10          -in       10,11,12,13 # * = True
10,11,12,13 -contains 10          # * = True

10,11,12,13,14,10 -eq 10 # => 10, 10
10,11,12,13,14,10 -ne 10 # => 11, 12, 13, 14
10,11,12,13,14,10 -gt 10 # => 11, 12, 13, 14

#endregion

#region Typen Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Type_Operators' -ShowWindow 

# ! Ermitteln ob ein Objekt von einem Typ X ist:

(Get-Process)[0] -is [System.Diagnostics.Process] # * = Wahr
(Get-Process)    -is [System.Array]               # * = Wahr

          '2015-03-18' -is [DateTime]
[DateTime]'2015-03-18' -is [DateTime]

# ! Ein Objekt in einen anderen Typen konvertieren:

[DateTime]'2015-03-18'
# ODER:
'2015-03-18' -as [DateTime]

# TIPP - Objekt-Typ auslesen:

'2015-03-18'.GetType()
(Get-Process)[0].GetType()

# TIPP - Vererbungshierarchie auflisten:

'2015-03-18'.PSTypeNames
(Get-Process)[0].PSTypeNames

#endregion

#region Format-Operator

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Operators' -ShowWindow

# ! Anstelle folgende Zeilen...:
$zahlen = 10, 11, 99, 230, 1024
"Wert 1 ist $($zahlen[0]), der letzte Wert ist $($zahlen[3]) und die anderen sind: $($zahlen[1]), $($zahlen[2])"
# ! ... kann mittels dem -f Operator das wie folgt vereinfacht werden:
'Wert 1 ist {0}, der letzte Wert ist {4} und die anderen sind: {1}, {2}, {3}' -f 10, 11, 99, 230, 1024

# ! SYNTAX: 'FORMAT' -f Value[, Value, Value, ...]

'Zahlenformat: {0}'          -f 123456.6789
'Zahlenformat: {0:#,##}'     -f 123456.6789 # ! 1.000-Trennzeichen
'Zahlenformat: {0:000.00}'   -f 12.456      # ! Anzahl Führende 0 & Nachkommastellen
'Zahlenformat: {0:#,##0.00}' -f 123456.6789
'Zahlenformat: {0:c2}'       -f 123456.6789 # ! Currency mit 2 Nachkommastellen

'Datumsformat: {0:yy yyyy M MM MMM MMMM d dd ddd dddd gg h hh t tt H HH zz zzz m mm s ss fffffff}' -f (Get-Date) # 20
'Datumsformat: {0:yyyy-MM-ddTHH:mm:ss}' -f (Get-Date) # 2020-09-12T17:33:45
'Datumsformat: {0}'   -f (Get-Date) # 12.09.2020 17:33:45
'Datumsformat: {0:d}' -f (Get-Date) # 12.09.2020
'Datumsformat: {0:D}' -f (Get-Date) # Sonntag, 12. September 2020
'Datumsformat: {0:f}' -f (Get-Date) # Sonntag, 12. September 2020 17:33
'Datumsformat: {0:F}' -f (Get-Date) # Sonntag, 12. September 2020 17:33:45
'Datumsformat: {0:g}' -f (Get-Date) # 12.09.2020 17:33
'Datumsformat: {0:G}' -f (Get-Date) # 12.09.2020 17:33:45
'Datumsformat: {0:m}' -f (Get-Date) # 12. September
'Datumsformat: {0:r}' -f (Get-Date) # Sun, 12. September 2020 17:33:45 (RFC1123)
'Datumsformat: {0:s}' -f (Get-Date) # 2020-09-12T17:33:45
'Datumsformat: {0:t}' -f (Get-Date) # 17:33
'Datumsformat: {0:T}' -f (Get-Date) # 17:33:45
'Datumsformat: {0:u}' -f (Get-Date) # 2020-09-12T17:33:45 (universal time)
'Datumsformat: {0:U}' -f (Get-Date) # Sonntag, 12. September 2020 17:33:45 (universal time)
'Datumsformat: {0:y}' -f (Get-Date) # September 2020

# ! ACHTUNG das Rückgabeobjekt aus einer -F Operation ist immer ein String, daher ist folgendes nicht mehr möglich:

$x = '{0}' -f (Get-Date)
$x.AddDays(100)
# TIPP - Besser so:
$x = (Get-Date)
$x.AddDays(100)

# ! Über den -f Operator kann der eingesetzte Wert auch links oder rechtsbünding in einer festen Breite angegeben werden:

'{0,-10:0.0} | {1,-10:0.0} | {2,-10:0.0}' -f   'Wert A', 'Wert B', 'Sum'
'{0, 10:0.0} | {1, 10:0.0} | {2, 10:0.0}' -f   12,  23, 167.889
'{0, 10:0.0} | {1, 10:0.0} | {2, 10:0.0}' -f  212, 123,  67.89
'{0, 10:0.0} | {1, 10:0.0} | {2, 10:0.0}' -f 3319,   3,   7.8

# ! Beispiele:

$pcs = 1..100 | ForEach-Object -Process { 'PC{0:000}' -f $_ }
$session = New-PSSession -ComputerName $pcs
Invoke-Command -Session $session -ScriptBlock { Restart-Computer }

"Log_{0:yyyyMMddHH}.log" -f (Get-Date)

#endregion

#region String aufteilen

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Split' -ShowWindow

$env:PSModulePath -split ';'

#endregion

#region Ein String-Array zu einen String zusammenführen

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Join' -ShowWindow

$result = Get-Service | Select-Object -ExpandProperty 'Name'
$result -join ', '

#endregion

#region Suchen und ersetzen

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Comparison_Operators' -ShowWindow

'Hallo Köln!' -iReplace 'Köln', 'Würzburg'

#endregion

#region Spezial-Operatoren

# READ Weiterführende und Nachschlage-Informationen:
Get-Help -Name 'about_Operators' -ShowWindow

# ! & Call-Operator:

# Führt einen Befehl, ein Skript oder einen Skriptblock aus. Mit dem Aufrufoperator, können Sie Befehle ausführen, die in Variablen gespeichert und durch Zeichenketten oder Skriptblöcke dargestellt sind. Der Aufrufoperator wird in einem untergeordneten Bereich ausgeführt (s. about_scopes)
$c = { Get-Service -Name 'Spooler' }
& $c

# ! . Call-Operator:

# Führt ein Skript im aktuellen Bereich aus, so dass alle Funktionen, Aliase und Variablen, die das Skript erstellt, dem aktuellen Bereich hinzugefügt werden.

. 'c:\scripts\sample.ps1'

# ! Cast-Operator:

# Konvertiert oder begrenzt Objekte auf den angegebenen Typ. Wenn die Objekte nicht konvertiert werden können, generiert PowerShell einen Fehler.

[datetime]$birthday = "1/20/88" ; $birthday
[int64]$a = 34                  ; $a

# ! .. Range-Operator:

# Stellt die sequentiellen Ganzzahlen in einem ganzzahligen Array dar, das eine obere und untere Grenze aufweist.

1..10
10..1

# ! :: Statische-Member-Operator:

# ! Ruft den Operator für statische Eigenschaften und Methoden einer .NET Framework-Klasse auf. Um die statischen Eigenschaften und Methoden eines Objekts zu finden, verwenden Sie den Static-Parameter des Cmdlets Get-Member.

[datetime]::Now.AddHours(-1)
[Math]::PI

[Math] | Get-Member -Static

#endregion

#region PowerShell 7 - Neue und geänderte Operatoren

# ! Split-Operator wurde erweitert:

# * ALT: Splittet nur 3 Elemente von Links:
"a b c d e" -split " ",  3

# NEU: Splittet nur 3 Elemente von Rechts:
"a b c d e" -split " ", -3

# ! Ein dreiteiliger Inline-If-Operator (Ternary-Operator (a ? b : c)):

# WENN ? DANN : SONST
  ($PSCulture -ieq "de-DE" ? "Die PS-Sprache steht auf deutsch-Deutschland." : "Die PS-Sprache steht auf $PSCulture.") | Write-Warning

# ! Pipeline-Verkettung-Operatoren && und || (Pipeline chain operators):

# Beschreibt die Verkettung von Pipelines mit && und || Operatoren:
Get-Help -Name "about_Pipeline_Chain_Operators" -ShowWindow

1/0.1 && "Ich werde ausgeführt wenn die vorherige Anweisung ERFOLGREICH war." | Write-Warning

1/0   || "Ich werde ausgeführt wenn die vorherige Anweisung ERFOLGLOS war."   | Write-Warning

# ! NULL-Sammel-Operator ?? (Null-coalescing operator):

Get-Help -Name "about_Operators" -ShowWindow

# In Abhängigkeit von einem NULL-Wert soll eine Fallunterscheidung statt finden, was bist dato wie folgt implementiert werden musste:

$a = $null # bzw. $a = 'Dies ist der Inhalt von $a'
if($null -ne $a) {
    $a | Write-Warning
} 
else {
    '$a ist ohne Inhalt!' | Write-Warning
}

# TODO Dieses Konstrukt lässt sich nun vereinfacht wie folgt implementieren:

$a = $null # bzw. $a = 'Dies ist der Inhalt von $a'
# Sollte $a gleich NULL sein, wird anstelle dessen der String zurückgegeben:
$a ?? '$a ist ohne Inhalt!' | Write-Warning

# * Die NULL-Sammeloperatoren sind rechtsassoziativ d.h. $a ?? $b ?? $c wird wie folgt abgearbeitet:

$a = $null
$b = $null
$c = 3
$a ?? $b ?? $c
# identisch mit:
$a ?? ($b ?? $c)

# ! NULL-Zuweisungs-Operatoren ??=, ?. (Null-conditional operators):

Get-Help -Name "about_Operators" -ShowWindow

# Sollte eine Variable NULL enthalten, soll dieser einen Default-Wert zugewiesen werden, was bist dato wie folgt implementiert werden musste:

$a = $null # bzw. $a = 123
if($null -eq $a) {
    $a = 'Diesen String als Default-Wert setzen, wenn $a gleich NULL ist.'
}
$a | Write-Warning

# TODO Dieses Konstrukt lässt sich nun vereinfacht wie folgt implementieren:

$a = $null # bzw. $a = 123
$a ??= 'Diesen String als Default-Wert setzen, wenn $a gleich NULL ist.'
$a | Write-Warning

# ! NULL-Bedingung-Operator (${a}?.MemberName):

Get-ExperimentalFeature -Name "PSNullConditionalOperators" | Enable-ExperimentalFeature

$t = Get-Process -Name "SvcHost" | Select-Object -First 1
$t.ToString() # Geht!

$t = Get-Process -Name "GibtEsNicht" | Select-Object -First 1
# * ALT: Problematisch, da eine Exception ausgelöst wird ($t = NULL)
$t.ToString()

# NEU: Lösung: Löst keinen Exception aus, wenn $t gleich NULL ist
${t}?.ToString()

#endregion

# TODO QUIZ - https://forms.office.com/Pages/ResponsePage.aspx?id=DQSIkWdsW0yxEjajBLZtrQAAAAAAAAAAAAa__Yp1xwFUMFFZSE85SkIyNFEyVFYzR1NYRktLU09QSy4u