PowerShell 學習筆記 - 1 PS Core 基礎

PowerShell 學習筆記 - 1 PS Core 基礎

本章主要探討 PowerShell 核心,主要基於 Linux 平臺上的 PowerShell Core 實現,實際上於 Windows PowerShell 平臺上進行的實驗得到的結果也不會有太大區別:linux

# 運行容器
C:\Users\chuny>docker run -it --name ps-test-base mcr.microsoft.com/powershell:centos-7
PowerShell 6.1.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

PS /> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
6      1      0


PS /> $PSVersionTable.OS
Linux 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:55:56 UTC 2018

學習一門 Shell 首先要從記憶他的命令(族)作起,但 UNIX Shell 及其歷史演進中的開源化特質,使得 Linux 內 bash 可調用項的命名系統支離破碎,以以下二進制爲例:docker

  • ls / wc:源於兩個簡寫 list 與 word count
  • uname:源於系統調用 uname()
  • date:源於非縮寫的英文單詞 date
PS /> ls |wc -l
19
PS /> uname
Linux
PS /> date
Sun Sep 16 06:59:33 UTC 2018

三個經常使用二進制的命名源於三種不一樣的模式,非 UNIX 專業戶單單從這些名字上就可能會產生恐懼感。shell

Windows 世界內,經過原住民 CMD 調用的原生應用命名也有殊途同歸之妙:windows

C:\Users\chuny>taskmgr.exe

C:\Users\chuny>calc.exe

C:\Users\chuny>ipconfig.exe

PowerShell 採起了不一樣的策略,設計了更加簡單好記的 cmdlet 命名範式,cmdlet 實際上並非命令,而是託管於 .Net 平臺的實例,關於 cmdlet 是什麼的討論已經遠遠超出了本系列的初衷,實際通常腳本工做中,造成一段腳本依靠的是粘合原生功能造成的工做流,而沒必要關心這些原生功能是如何實現的。centos

cmdlet 深刻內容參考: Windows PowerShell Cmdlet Concepts

例如 Linux 中,單單一個管道的底層實現即是千行規模的,更沒必要說創建在各類庫上面的二進制了。bash

Linux 管道的實現思路: How Linux pipes work under the hood

所以,cmdlet 即平臺相關的原生功能的抽象,以以下的一段獲取時間的代碼片斷爲例:ide

PS /> $dateNow = Get-Date
PS /> $dateNow

Sunday, September 16, 2018 6:55:39 AM
PS /> $dateNow.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DateTime                                 System.ValueType
PS /> $dateNow.GetType().Name
DateTime
PS /> $dateNow

Sunday, September 16, 2018 6:55:39 AM

cmdlet

Get-Date 爲一個標準的預置 PowerShell cmdlet,
PowerShell 使用動-名命名範式,即每一個 cmdlet 標準名稱都由一個標識意圖的動詞、連字符以及一個標的物名詞組成。函數

預置 PowerShell cmdlet:因爲 PowerShell 啓動時默認的載入 Microsoft.PowerShell.Utility 模塊,所以其中的 cmdlet 是開箱即用的,或者說是 預置的。

PowerShell 同時內建了高效的幫助系統供用戶自學 cmdlet 等的使用方式,以搜索日期相關的 cmdlet 爲例:post

PS /> Get-Help -Category cmdlet Date

Name                              Category  Module                    Synopsis
----                              --------  ------                    --------
Update-Help                       Cmdlet    Microsoft.PowerShell.Core ...
Get-Date                          Cmdlet    Microsoft.PowerShell.U... ...
Set-Date                          Cmdlet    Microsoft.PowerShell.U... ...
Update-FormatData                 Cmdlet    Microsoft.PowerShell.U... ...
Update-TypeData                   Cmdlet    Microsoft.PowerShell.U... ...

Get-Help 即爲 PowerShell 體系中的標準幫助函數,相似於 UNIX 世界中的 manGet-Help -Category cmdlet Date 表明在 cmdlet 這一種類中搜索 Date 這一字符串相關的項目,Get-help 可經過查看自身得到基本幫助,即 Get-Help Get-Help學習

同時,PowerShell 也提供了一個 cmdlet 以供精確的命令搜索

PS /> Get-Command -Noun Date

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Get-Date                                           6.1.0.0    Microsoft.PowerShell.Utility
Cmdlet          Set-Date                                           6.1.0.0    Microsoft.PowerShell.Utility

這次對 Date 的搜索精確到了獲取標的物名詞可用的命令種類,獲取到了 Dategettersetter

同時,PowerShell 對於 cmdlet 也是大小寫不敏感的,例如:

PS /> Get-DaTe

Sunday, September 16, 2018 7:51:50 AM
PS /> get-date

Sunday, September 16, 2018 7:51:52 AM

但做爲更好的工程實踐,建議嚴格遵照 cmdlet 原始寫法,實際上交互式 Shell 中只需在輸入 cmdlet 後利用 Tab 補全便可得到原始寫法。

PowerShell 也提供別名系統用以簡化命令輸入,但建議只在交互式 Shell 中使用,例以下行中的 gal 又是什麼呢:

PS /> (gal).Name.Length
110

# 實際上 gal 即 Get-Alias 的別名,直接運行 gal 能夠得到現已加載的模塊中存在的別名列表
PS /> (Get-Alias gal).Definition
Get-Alias

若是生產環境腳本中大量出現這樣的別名勢必大大影響可讀性。

變量

$dateNow = Get-Date 中的 $dateNow 聲明一個名爲 dateNow變量,變量亦能夠在創建時不指定值:

PS /> $newVar
PS /> $newVar
# 無輸出

變量名能夠包含下劃線字符,也能夠是任何字母數字字符。變量在 使用時,始終使用$ 字符加變量名稱指定變量

$dateNow = Get-Date等式右方計算返回的對象賦予左方,注意此時左方爲一個肯定的實例,二者具有一樣的類型,以以下的片斷爲例,二者類型相同,然而值不同,$dateNow 已是最近一次賦值時綁定的對象,Get-Date 將使用默認值初始化並返回一個匿名對象:

PS /> $dateNow.GetTypeCode()
DateTime
PS /> (Get-Date).GetTypeCode()
DateTime

# $dateNow 是一個實例
PS /> $dateNow.GetType.IsInstance
True

# 兩個匿名對象的 Hash 值不一樣
PS /> (Get-Date).GetHashCode()
433633629
PS /> (Get-Date).GetHashCode()
431809023

對象操做

PowerShell 中的變量存儲對象,所以其中對變量的操做將遵循面向對象的方式進行。

Get-Member cmdlet 用於獲取變量(對象)中的成員,例如對於 $dateNow 其具有屬性 Year 與成員方法 ToType

PS /> $dateNow | Get-Member -Name Year


   TypeName: System.DateTime

Name MemberType Definition
---- ---------- ----------
Year Property   int Year {get;}


PS /> $dateNow | Get-Member -Name ToType


   TypeName: System.DateTime

Name   MemberType Definition
----   ---------- ----------
ToType Method     System.Object IConvertible.ToType(type conversionType, System.IFormatProvider provider)

所以,對於對象成員的調用也經過 . 運算符實現:

# 方法調用
PS /> $dateNow.ToString()
9/16/18 7:23:57 AM

# 成員調用(即調用該成員的 getter 方法,如不存在直接返回值)
PS /> $dateNow.Year
2018

# 成員更新(即調用該成員的 setter 方法,如不存在直接寫值,此處該屬性已經被聲明爲只讀屬性,因此沒法更改)
PS /> $dateNow.Year = -2
'Year' is a ReadOnly property.
At line:1 char:1
+ $dateNow.Year = -2
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

對於 PowerShell 工做流的造成也將圍繞對象與管道展開,以一段獲取並格式化生成列表的 AJAX 請求爲例:

根據快遞 100 提供的開放查詢 API,能夠查詢到某快遞公司某單號的具體遞送信息,以下爲例:

# 定義變量
$baseUrl = "www.kuaidi100.com/query"
$scheme = "http"
$company = "yuantong"
$postId = "11111111111"

# 發送請求
$ret = Invoke-RestMethod -Uri ($scheme + "://" + $baseUrl + "?type=" + $company + "&postid=" + $postId)

# Get-Member 檢查該返回對象中的成員
PS /> $ret | Get-Member
   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
com         NoteProperty string com=yuantong
condition   NoteProperty string condition=00
data        NoteProperty Object[] data=System.Object[]
ischeck     NoteProperty string ischeck=0
message     NoteProperty string message=ok
nu          NoteProperty string nu=11111111111
state       NoteProperty string state=0
status      NoteProperty string status=200

# $ret 的返回值爲 200 SUCCESS
PS /> $ret.status
200

# 經過管道鏈接,即可輸出只包含固定字段的記錄中的某些項(例如前五項)
PS /> $ret.data | Format-Table -Property Time, Context | select -First 5

time                                                        context
----                                                        -------
2018-09-14 10:20:06                                         賈崗社區28號樓1單元101室媽媽驛站已發出自提短信,請上門自提,聯繫電話0371-60997919
2018-09-14 10:19:06                                         快件已到達賈崗社區28號樓1單元101室媽媽驛站,聯繫電話0371-60997919
2018-08-23 09:58:40                                         華偉家園東門頭房快遞服務中心媽媽驛站已發出自提短信,請上門自 提,聯繫電話17662528999
相關文章
相關標籤/搜索