2016-01-20 95 views
5

我從Powershell查詢得到以下輸出。我沒有訪問服務器來運行查詢,所以我沒有選擇來影響輸出格式。Powershell格式文本文件

例子:

Name   : folderC 
FullName  : D:\folderA\folderB\folderC 
Length   : 
CreationTime : 2/8/2014 11:12:58 AM 
LastAccessTime : 2/8/2014 11:12:58 AM 

Name   : filename.txt 
FullName  : D:\folderA\folderB\filename.txt 
Length   : 71560192 
CreationTime : 11/25/2015 3:10:43 PM 
LastAccessTime : 11/25/2015 3:10:43 PM 

所以我的問題是我怎麼能格式化以上內容來獲得更多的東西可用,也許像一個表格式,像這樣:

Name|FullName|Length|CreationTime|LastAccessTime 
+2

是輸出對象還是文本?通過'Get-Member'管理它(在輸出的開始處查找'TypeName')。 – alroc

回答

3

作爲@alroc筆記對這個問題的評論,可能對象可用於OP,因爲他們聲明輸出是「來自Powershell查詢」 - 如果是這樣,使用常用的cmdlet簡單地重新格式化對象數組就是選項。
相比之下,此答案假設只有文字表示法(如問題所示)可用。

Dave Sexton's answer是一個更簡單,更優雅的選擇,如果:

  • 輸入沒有值(OP的樣品輸入一樣)。
  • 輸入文件足夠小,可以作爲一個整體讀入內存。

考慮下面的方法避免了以上問題和/或,如果你想在輸入如何轉換成自定義對象更多的控制,尤其是相對於創造與其他類型相比[string]屬性:延長下面的toObj()函數(如所寫,所有屬性也只是字符串)。


Get-Content File | % ` 
    -begin { 
    function toObj([string[]] $lines) { 
     $keysAndValues = $lines -split '(?<=^[^ :]+)\s*: ' 
     $htProps = @{} 
     for ($i = 0; $i -lt $keysAndValues.Count; $i += 2) { 
     $htProps.($keysAndValues[$i]) = $keysAndValues[$i+1] 
     } 
     return [PSCustomObject] $htProps 
    } 
    $lines = @() 
    } ` 
    -process { 
    if ($_.trim() -ne '') { 
     $lines += $_ 
    } else { 
     if ($lines) { toObj $lines } 
     $lines = @() 
    } 
    } ` 
    -end { 
    if ($lines) { toObj $lines } 
    } | Format-Table 

說明:

  • ForEach-Object用途(%)配有獨立beginprocess,和end塊。

  • -begin,在開始時執行一次

    • 定義輔助函數toObj()該連續非空輸入線的一個塊轉換到單個自定義對象。

      • toObj()將一行數組拆分爲一個連續的鍵值元素數組,將該數組轉換爲散列表,然後將其轉換爲自定義對象。

      • 初始化數組$lines,將存儲連續的非空輸入線

    • -process塊的單個塊的線,對於每一個輸入行執行

    • 如果手邊的輸入行不是空格:將其添加到存儲的連續非空輸入行的當前塊在數組$lines

    • 否則:提交當前塊爲toObj()轉換爲自定義對象,然後重置$lines數組以啓動下一個塊。實際上,對於每個段落(非空行的運行)調用toObj()

  • -end塊,執行一旦底:

    • 提交最後一段至toObj()用於轉化爲一個自定義對象。
  • 最後,將得到的自定義對象數組傳遞給Format-Table

+0

真棒 - 這對我有用! – ratanmalko

4

我認爲你需要有平等分割的文本記錄,更換冒號,這樣就可以使用ConvertFrom-StringData是把每個記錄到一個哈希然後可以送入新物體轉換變成一個物體。然後可以使用ConvertTo-Csv完成將對象輸出爲管道分隔數據。像這樣:

$x = @" 
Name   : folderC 
FullName  : D:\folderA\folderB\folderC 
Length   : 0 
CreationTime : 2/8/2014 11:12:58 AM 
LastAccessTime : 2/8/2014 11:12:58 AM 

Name   : filename.txt 
FullName  : D:\folderA\folderB\filename.txt 
Length   : 71560192 
CreationTime : 11/25/2015 3:10:43 PM 
LastAccessTime : 11/25/2015 3:10:43 PM 
"@ 

($x -split '[\r\n]+(?=Name)') | % { 
    $_ -replace '\s+:\s+', '=' 
} | % { 
    $_ | ConvertFrom-StringData 
} | % { 
    New-Object psobject -Property $_ 
} | ConvertTo-Csv -Delimiter '|' -NoTypeInformation 
+0

巧妙的塊分割方法和'ConvertFrom-StringData' /'New-Object'組合;唯一的問題是'ConvertFrom-StringData'將未加引號的序列解釋爲控制字符轉義。加倍輸入中的'\'實例應該修復'($ _ -replace'\ s +:\ s +','=')--replace'\\','\\'' – mklement0

+1

@ mklement0好點,可能需要用更大的數據集進行更多的測試。當他們沒有價值時,我認爲可能有一個問題。也許將字符串轉換爲帶引號的字符串可能是要走的路。進行替換:'$ _ -replace'\ s +:\ s +',''='「'並添加另一個'$ _ -replace'^ | $','''' –

+0

造成問題。引用不_幫助,不幸的是 - 'ConvertFrom-StringData'將它們保留爲文字。 – mklement0