2013-02-15 94 views
0

我有一系列文檔正在通過以下函數來設計用於統計每個文檔中的詞出現次數。這個函數可以很好地輸出到控制檯,但是現在我想生成一個包含信息的文本文件,但是文件名會附加到列表中的每個單詞上。我需要使用PowerShell的Out-File cmdlet幫助格式化輸出

我現在的控制檯輸出爲:

"processing document1 with x unique words occuring as follows" 
"word1  12" 
"word2  8" 
"word3  3" 
"word4  4" 
"word5  1" 

我想在這個格式的分隔符的文件:

document1;word1;12 
document1;word2;8 
document1;word3;3 
document1;word4;4 
document1;word1;1 
document2;word1;16 
document2;word2;11 
document2;word3;9 
document2;word4;9 
document2;word1;13 

雖然下面的功能得到了我的話,並出現次數的名單,我有很難找出在哪裏或如何插入文件名變量,以便它打印在每行的開頭。 MSDN已經不足,樂於助人,大部分的地方我嘗試插入變量導致錯誤(見下文)

function Count-Words ($docs) { 
    $document = get-content $docs 
    $document = [string]::join(" ", $document)   
    $words = $document.split(" `t",[stringsplitoptions]::RemoveEmptyEntries)        
    $uniq = $words | sort -uniq 
    $words | % {[email protected]{}} {$wordhash[$_] += 1} 
    Write-Host $docs "contains" $wordhash.psbase.keys.count "unique words distributed as follows." 
    $frequency = $wordhash.psbase.keys | sort {$wordhash[$_]} 
    -1..-25 | %{ $frequency[$_]+" "+$wordhash[$frequency[$_]]} | Out-File c:\out-file-test.txt -append 
    $grouped = $words | group | sort count 

我需要創建一個字符串傳遞給了文件cmdlet的?這只是我在最後幾次嘗試中把錯誤的地方放在了什麼地方?我想了解爲什麼它會在特定的地方進行。現在我只是猜測,因爲我知道我不知道在哪裏可以讓out-file達到我選擇的結果。

我試過每PowerShell幫助格式化我的命令,用-$docs-FilePath,但每次我添加任何東西到out-file上面那段時間成功運行,我得到以下錯誤:

Out-File : Cannot validate argument on parameter 'Encoding'. The argument "c:\out-file-test.txt" does not bel 
ong to the set "unicode,utf7,utf8,utf32,ascii,bigendianunicode,default,oem" specified by the ValidateSet attribute. Sup 
ply an argument that is in the set and then try the command again. 
At C:\c.ps1:39 char:71 
+  -1..-25 | %{ $frequency[$_]+" "+$wordhash[$frequency[$_]]} | Out-File <<<< -$docs -width 1024 c:\users\x46332\co 
unt-test.txt -append 
    + CategoryInfo   : InvalidData: (:) [Out-File], ParameterBindingValidationException 
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.OutFileCommand 

回答

1

我改寫了最的代碼。您應該利用對象來使其更容易以您想要的方式進行格式化。這個分裂在「空間」和分組在一起。試試這個:

Function Count-Words ($paths) { 
    $output = @() 
    foreach ($path in $paths) { 
     $file = Get-ChildItem $path 
     ((Get-Content $file) -join " ").Split(" ", [System.StringSplitOptions]::RemoveEmptyEntries) | Group-Object | Select-Object -Property @{n="FileName";e={$file.BaseName}}, Name, Count | % { 
      $output += "$($_.FileName);$($_.Name);$($_.Count)" 
     } 
    } 
    $output | Out-File test-out2.txt -Append 
} 

$filepaths = ".\test.txt", ".\test2.txt" 

Count-Words -paths $filepaths 

它輸出就像你問(文檔;字;數)。如果您希望文檔名稱包含擴展名,請將$file.BaseName更改爲$file.Name。 Testoutput:

test;11;1 
test;9;2 
test;13;1 
test2;word11;5 
test2;word1;4 
test2;12;1 
test2;word2;2 
+1

難道你不能編譯一個'PSObjec的數組列出所有內容,然後使用「Export-CSV -delimiter」;「 -notypeinfo'獲取輸出?從I/O角度來看,這會更有效率(繞過管道),只寫出一次文件。 – alroc 2013-02-15 14:18:27

+0

@Graimer謝謝!這看起來不錯。這可能是我的環境的一個問題,但是當我如上所述運行代碼時,出現此錯誤......由於[System.Object []]不包含名爲'Split'的方法,所以方法調用失敗。 '在C:\ users \ x46332 \ desktop \ cgc \ counts.ps1:15 char:34'' +(Get-Content $ file).Split <<<<(「」,''[System.StringSplitOptions] :: RemoveEmptyEntries)| Group-Object | %{' '+ CategoryInfo:InvalidOperation:(Split:String)[],RuntimeException' '+ FullyQualifiedErrorId:MethodNotFound'任何想法?是否有'include'訪問類庫? – dwwilson66 2013-02-15 14:32:00

+0

...或者也許'(Get-Content $文件)。-split(「」,[System.StringSplitOptions] :: RemoveEmptyEntries)|組對象' – dwwilson66 2013-02-15 14:39:17

0

試試這個:

$docs = @("document1", "document2", ...) 

$docs | % { 
    $doc = $_ 
    Get-Content $doc ` 
    | % { $_.split(" `t",[stringsplitoptions]::RemoveEmptyEntries) } ` 
    | Group-Object ` 
    | select @{n="Document";e={$doc}}, Name, Count 
} | Export-CSV output.csv -Delimiter ";" -NoTypeInfo 

如果你想成爲一個功能,這個你可以做這樣的:

function Count-Words($docs) { 
    foreach ($doc in $docs) { 
    Get-Content $doc ` 
     | % { $_.split(" `t",[stringsplitoptions]::RemoveEmptyEntries) } ` 
     | Group-Object ` 
     | select @{n="Document";e={$doc}}, Name, Count 
    } 
} 

$files = @("document1", "document2", ...) 

Count-Words $files | Export-CSV output.csv -Delimiter ";" -NoTypeInfo 
+0

很好用,除了我只從路徑中的最後一個文件獲取數據。 '-append'不適用於我(我正在運行v2.0)'您是否知道PS2.0有任何解決方法來讀取一系列文件並追加結果? – dwwilson66 2013-02-15 16:01:49

+0

我使用的PowerShell 2.0,我得到了'output.csv'中所有輸入文件的結果。但是,作爲解決方法,您可以嘗試像'| ConvertTo-Csv -Delimiter「;」 -NoTypeInfo | Out-File output.csv -Append'。 – 2013-02-15 18:15:29

0

略有不同的方法:

function Get-WordCounts ($doc) 
{ 
     $text_ = [IO.File]::ReadAllText($doc.fullname) 

     $WordHash = @{} 

     $text_ -split '\b' -match '\w+'| 
     foreach {$WordHash[$_]++} 

     $WordHash.GetEnumerator() | 
     foreach { 
     New-Object PSObject -Property @{ 
              Word  = $_.Key 
              Count = $_.Value 
             } 
       } 
    } 


$docs = gci c:\testfiles\*.txt | 
sort name 

&{ 
foreach ($doc in dir $docs) 
     { 
      Get-WordCounts $doc | 
      sort Count -Descending | 
      foreach { 
       (&{$doc.Name;$_.Word;$_.Count}) -join ';' 
      } 
     } 
} | out-file c:\somedir\wordcounts.txt 
+0

不錯的解決方案!雖然我沒有看到輸出,但我努力將輸出輸出到「Out_File」卻不成功。運行沒有錯誤,但你沒有任何證實。你會在哪裏推薦我的'Out-File'?我正在考慮在'-join'附近;'......' – dwwilson66 2013-02-15 16:28:23

+0

將foreach對象輸出發送到管道的簡單方法是將循環包裝到&{}中。我用一個例子更新了答案。 – mjolinor 2013-02-15 16:34:44