今年(2018)早些時候,Powershell Core[1] 以 MIT[2] 開源協議釋出了正式可用版(GA)[3]。PowerShell 算不上是新技術。自 2006 年為 Windows 釋出了第一版 PowerShell 以來,PowerShell 的建立者在結合了[4] Unⅸ shell 的強大和靈活的同時也在彌補他們所意識到的缺點,特別是從組合命令中獲取值時所要進行的文字操作。
在釋出了 5 個主要版本之後,PowerShell 已經可以在所有主流作業系統上(包括 OS X 和 Linux)本地運行同樣創新的 shell 和命令列環境。一些人(應該說是大多數人)可能依舊在嘲弄這位誕生於 Windows 的闖入者的大膽和冒失:為那些遠古以來(從千禧年開始算不算?)便存在著強大的 shell 環境的平臺引薦自己。在本帖中,我希望可以將 PowerShell 的優勢介紹給大家,甚至是那些經驗老道的使用者。
跨平臺一致性
如果你計劃將指令碼從一個執行環境遷移到另一個平臺時,你需要確保只使用了那些在兩個平臺下都起作用的命令和語法。比如在 GNU 系統中,你可以透過以下方式獲取昨天的日期:
-
date --date="1 day ago"
在 BSD 系統中(比如 OS X),上述語法將沒辦法工作,因為 BSD 的 date 工具需要以下語法:
-
date -v -1d
因為 PowerShell 具有寬鬆的許可證,並且在所有的平臺都有構建,所以你可以把 PowerShell 和你的應用一起打包。因此,當你的指令碼執行在標的系統中時,它們會執行在一樣的 shell 環境中,使用與你的測試環境中同樣的命令實現。
物件和結構化資料
*nix 命令和工具依賴於你使用和操控非結構化資料的能力。對於那些長期活在 sed
、 grep
和 awk
環境下的人們來說,這可能是小菜一碟,但現在有更好的選擇。
讓我們使用 PowerShell 重寫那個獲取昨天日期的實體。為了獲取當前日期,使用 Get-Date
cmdlet(讀作 “commandlet”):
-
> Get-Date
-
-
Sunday, January 21, 2018 8:12:41 PM
你所看到的輸出實際上並不是一個文字字串。不如說,這是 .Net Core 物件的一個字串表現形式。就像任何 OOP 環境中的物件一樣,它具有型別以及你可以呼叫的方法。
讓我們來證明這一點:
-
> $(Get-Date).GetType().FullName
-
System.DateTime
$(...)
語法就像你所期望的 POSIX shell 中那樣,計算括弧中的命令然後替換整個運算式。但是在 PowerShell 中,這種運算式中的 $
是可選的。並且,最重要的是,結果是一個 .Net 物件,而不是文字。因此我們可以呼叫該物件中的 GetType()
方法來獲取該物件型別(類似於 Java 中的 Class
物件),FullName
屬性[5] 則用來獲取該型別的全稱。
那麼,這種物件導向的 shell 是如何讓你的工作變得更加簡單呢?
首先,你可將任何物件排進 Get-Member
cmdlet 來檢視它提供的所有方法和屬性。
-
> (Get-Date) | Get-Member
-
PS /home/yevster/Documents/ArticlesInProgress> $(Get-Date) | Get-Member
-
-
-
TypeName: System.DateTime
-
-
Name MemberType Definition
-
---- ---------- ----------
-
Add Method datetime Add(timespan value)
-
AddDays Method datetime AddDays(double value)
-
AddHours Method datetime AddHours(double value)
-
AddMilliseconds Method datetime AddMilliseconds(double value)
-
AddMinutes Method datetime AddMinutes(double value)
-
AddMonths Method datetime AddMonths(int months)
-
AddSeconds Method datetime AddSeconds(double value)
-
AddTicks Method datetime AddTicks(long value)
-
AddYears Method datetime AddYears(int value)
-
CompareTo Method int CompareTo(System.Object value), int ...
你可以很快的看到 DateTime 物件具有一個 AddDays
方法,從而可以使用它來快速的獲取昨天的日期:
-
> (Get-Date).AddDays(-1)
-
-
Saturday, January 20, 2018 8:24:42 PM
為了做一些更刺激的事,讓我們呼叫 Yahoo 的天氣服務(因為它不需要 API 令牌)然後獲取你的本地天氣。
-
$city="Boston"
-
$state="MA"
-
$url="https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22${city}%2C%20${state}%22)&format;=json&env;=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
現在,我們可以使用老派的方法然後直接執行 curl $url
來獲取 JSON 二進位制物件,或者……
-
$weather=(Invoke-RestMethod $url)
如果你查看了 $weather
型別(執行 echo $weather.GetType().FullName
),你將會發現它是一個 PSCustomObject
。這是一個用來反射 JSON 結構的動態物件。
然後 PowerShell 可以透過 tab 補齊來幫助你完成命令輸入。只需要輸入 $weather.
(確報包含了 .
)然後按下 Tab
鍵。你將看到所有根級別的 JSON 鍵。輸入其中的一個,然後跟上 .
,再一次按下 Tab
鍵,你將看到它所有的子鍵(如果有的話)。
因此,你可以輕易的導航到你所想要的資料:
-
> echo $weather.query.results.channel.atmosphere.pressure
-
1019.0
-
-
> echo $weather.query.results.channel.wind.chill 41
並且如果你有非結構化的 JSON 或 CSV 資料(透過外部命令傳回的),只需要將它相應的排進 ConverFrom-Json
或 ConvertFrom-CSV
cmdlet,然後你可以得到一個漂亮乾凈的物件。
計算 vs. 自動化
我們使用 shell 用於兩種目的。一個是用於計算,執行獨立的命令然後手動響應它們的輸出。另一個是自動化,透過寫指令碼執行多個命令,然後以程式設計的方式相應它們的輸出。
我們大多數人都能發現這兩種目的在 shell 上的不同且互相衝突的要求。計算任務要求 shell 簡潔明瞭。使用者輸入的越少越好。但如果使用者輸入對其他使用者來說幾乎難以理解,那這一點就不重要了。指令碼,從另一個角度來講是程式碼。可讀性和可維護性是關鍵。這一方面,POSIX 工具通常是失敗的。雖然一些命令通常會為它們的引數提供簡潔明瞭的語法(如:-f
和 --force
),但是命令名字本身就不簡潔明瞭。
PowerShell 提供了幾個機制來消除這種浮士德式的平衡。
首先,tab 補齊可以消除鍵入引數名的需要。比如:鍵入 Get-Random -Mi
,按下 Tab
然後 PowerShell 將會為你完成引數:Get-Random -Minimum
。但是如果你想更簡潔一些,你甚至不需要按下 Tab
。如下所示,PowerShell 可以理解:
-
Get-Random -Mi 1 -Ma 10
因為 Mi
和 Ma
每一個都具有獨立不同的補齊。
你可能已經留意到所有的 PowerShell cmdlet 名稱具有動名詞結構。這有助於指令碼的可讀性,但是你可能不想一而再、再而三的鍵入 Get-
。所以並不需要!如果你之間鍵入了一個名詞而沒有動詞的話,PowerShell 將查詢帶有該名詞的 Get-
命令。
小心:儘管 PowerShell 不區分大小寫,但在使用 PowerShell 命令是時,名詞首字母大寫是一個好習慣。比如,鍵入
date
將會呼叫系統中的date
工具。鍵入Date
將會呼叫 PowerShell 的Get-Date
cmdlet。
如果這還不夠,PowerShell 還提供了別名,用來建立簡單的名字。比如,如果鍵入 alias -name cd
,你將會發現 cd
在 PowerShell 實際上時 Set-Location
命令的別名。
所以回顧以下 —— 你可以使用強大的 tab 補全、別名,和名詞補全來保持命令名詞簡潔、自動化和一致性引數名截斷,與此同時還可以享受豐富、可讀的語法格式。
那麼……你看呢?
這些只是 PowerShell 的一部分優勢。還有更多特性和 cmdlet,我還沒討論(如果你想弄哭 grep
的話,可以檢視 Where-Object[6] 或其別稱 ?
)。如果你有點懷舊的話,PowerShell 可以為你載入原來的本地工具。但是給自己足夠的時間來適應 PowerShell 面向物件 cmdlet 的世界,然後你將發現自己會選擇忘記回去的路。
via: https://opensource.com/article/18/2/powershell-people
作者:Yev Bronshteyn[8] 譯者:sanfusu 校對:wxy