給大家安利一下 PowerShell
今年(2018)早些時候,Powershell Core 以 MIT 開源協議發布了正式可用版(GA)。PowerShell 算不上是新技術。自 2006 年為 Windows 發布了第一版 PowerShell 以來,PowerShell 的創建者在結合了 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
屬性 則用來獲取該類型的全稱。
那麼,這種對象導向的 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 或其別稱 ?
)。如果你有點懷舊的話,PowerShell 可以為你載入原來的本地工具。但是給自己足夠的時間來適應 PowerShell 面向對象 cmdlet 的世界,然後你將發現自己會選擇忘記回去的路。
via: https://opensource.com/article/18/2/powershell-people
作者:Yev Bronshteyn 譯者:sanfusu 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive