天天看點

使用管道符在PowerShell中進行各種資料操作

最近在教育訓練powershell,在講到pipeline的時候,對于我這種長期和資料(資料庫)打交道的人來說,覺得很實用,是以寫此博文,記錄一下。

無論是在linux中寫bash腳本還是在window上寫powershell,管道符”|“是一個非常有用的工具。它提供了将前一個指令的輸出作為下一個指令的輸入的功能。在資料進行中,我們也可以使用管道符對資料進行各種操作。

先說導入導出是為了能夠為接下來的資料處理準備資料。在powershell中我們也可以通過各種get-xxx指令獲得各種各樣需要的資料,但是并不是所有作業系統和各個版本的powershell都支援某個指令的。比如get-volume指令,用于獲得每個磁盤的資訊,但是這個指令不能在win7下運作,隻能在win8或win2012server下運作。

最常見,最簡單的外部資料源就是csv檔案了。我們可以使用export-csv指令将powershell中的對象轉換為csv格式,持久化到磁盤上。比如我們将目前的所有程序資訊導出為csv檔案,指令為:

get-process | export-csv c:\test.csv -encoding unicode

(注意,如果是有中文内容建議設定encoding為unicode或者utf8)

import-csv指令是導入外部的csv檔案到記憶體。比較剛才導出的csv檔案,我們接下來要對這個檔案進行處理。我們可以将檔案的内容儲存到變量$data中。指令為:

$data=import-csv c:\test.csv -encoding unicode

當然,我們也可以先進行類型轉換,然後儲存。指令為:

$data | convertto-csv | out-file c:\test.csv -encoding utf8

前面我們已經将csv的内容載入到$data變量中了,那麼如果我們要按照某一個字段排序,可以使用sort-object指令。

比如我們要name這個字段排序,并輸出排序後的結果,那麼指令為:

$data | sort-object name

也可以簡寫為:

$data | sort name

如果是需要多個字段排序,那麼可以将字段列在後面,字段之間用逗号隔開。

$data | sort name,handles

如果是逆向排序,那麼需要在字段後面加參數-descending

$data | sort name –descending

選取相當于sql中的select指令。對應的powershell指令是select-object,可以簡寫為select。該指令後面跟上要選取的列名即可。如果是要選取所有的列,也可以使用*表示。

$data | select name,vm

選取所有列,那麼指令就是:

$data | select *

如果是隻選取前面幾條資料,那麼可以使用-first參數。比如我們按handles排序,隻檢視頭10條程序記錄的名字和handles。指令為:

$data | sort handles | select handles,name -first 10

另外還有參數-last選取的是最後幾條記錄,-skip可以選擇跳過一定記錄。

在select的時候,我們可以使用函數對其中的列進行運算,使用的文法是:

@{ 

  n='new column name'; 

  e={ $_.xxxcalc } 

}

其中的$_就是表示目前的記錄。

比如vm列記錄的是以byte為機關的資料,我們先建立一列名為”vm(mb)”,其值是換算成mb的結果,那麼我們可以寫為:

$data | select name,vm,@{n="vm(mb)";e={$_.vm/1mb}} 

說度量可能有點不是很清晰,其實就是對應sql中的聚合函數。比如 sum, max,min之類的,需要使用measure-object指令。比如要檢視有多少個程式,最小的handles和最大的handles,那麼指令是:

$data | measure-object -property handles -minimum -maximum

既然說到sql中的聚合函數,那麼自然就會想到另外一個關鍵字group by。在powershell中也有對應的指令group-object。如果我們想要按程序的name進行分組,檢視每個程序名對應的vm總大小。那麼我們可以先按name進行group:

$data | group-object name

這時我們可以看到系統傳回的結果有3列:count,name,group。而我們要進行聚合的vm值是在group中。這時需要用到前面提到的select指令。

$data | group-object name | select name,count,@{n="totalvm";e={($_.group | measure-object -property vm -sum).sum}}

過濾相當于slq中的where語句,在powershell中使用where-object指令。可以簡寫為where,甚至可以簡寫為”?”。在普通程式裡面我們遇到的比較運算和邏輯運算在powershell中有所不同,是這樣的參數:

comparison

case-insensitive

case-sensitive

equality

-eq

-ceq

inequality

-ne

-cne

greater than

-gt

-cgt

less than

-lt

-clt

greater than or equal to

-ge

-cge

less than or equal to

-le

-cle

wildcard equality

-like

-clike

-and 和-or用于邏輯運算。

仍然以前面load的$data為例,我們要檢視以w開頭的程序的handles和name,那麼指令為:

$data | ?{ $_.name -like 'w*'}| select handles,name

如果是多個條件,既要以w開頭,還要vm大于100m的程序,那麼指令為:

$data | ?{ $_.name -like 'w*' -and $_.vm -gt 100mb}| select handles,name,vm

枚舉相當于c#中的foreach函數,或者說是sql中的遊标,對于每一行資料,都進行一個運算或者函數處理。在powershell中對應的指令是foreach-object,可以簡寫為foreach,還可以進一步簡寫為”%“。

比如我們要将vm改為mb為機關,可以對每一行資料進行運算:

$data | % {$_.vm=$_.vm/1mb}

運作該指令後我們再檢視$data就會發現vm列已經改變了。

另外對于foreach指令,還有兩個比較有用的參數-begin –end,用于在做for循環之前調用和循環結束後調用。

比如我們想把某一列寫入一個檔案,我們可以在-begin時建立檔案,記錄開始的時間,然後foreach中append内容到檔案,最後把結束時間寫入:

$data | % -begin { get-date | out-file c:\test.txt } -process { $_.name | out-file c:\test.txt -append} -end { get-date | out-file c:\test.txt -append}