2016-12-24 96 views
1

你好,我的問題是有沒有更快的方式來搜索除了選擇字符串以外的文件中的短語。我需要在大約60k文件的第一行中找到某個特定的短語,但目前我正在做的事情對於我需要做的事情來說太慢了。 我曾嘗試做PowerShell快速搜索大量文件中的短語

(Select-String "Phrase I am looking for" (cat mylist1)).Filename > mylist2 

這給了我的2分30秒的成績,然後我試圖

cat mylist1| %{ if ((cat $_ -first 1) -match "Phrase I am looking for") {echo $_}} > mylist2 

這給了我2分鐘57秒的結果。是否有另一種方法通過大量文件來搜索字符串,這會縮短搜索時間?

回答

4

既然你至少有PowerShell的3.0,那麼你可以使用.WhereGet-Content-TotalCount,這應該幫助一些。 -TotalCount定義了正在讀取文件的行數。我看到您已經在使用其別名-First,不過這裏不會有太大的改變。

$path = "d:\temp" 
$matchingPattern = "function" 
(Get-ChildItem $path -File).Where{(Get-Content $_ -TotalCount 1) -match $matchingPattern } 

我會嘗試和測試這種對文件的60K,看看我能在平均htim得到。以上將返回第一行包含「功能」的文件對象。我的測試對60K的文件運行,但我的線可能更短。仍然在44秒內完成,所以這可能會幫助你

StreamReader通常也會擊敗Get-Content,但由於我們只得到一條線,我不認爲它會更有效。這在where子句中使用流讀取器並讀取第一行。

(Get-ChildItem $path -File).Where{([System.IO.File]::OpenText($_.Fullname).ReadLine()) -match $matchingPattern } 

請注意,上述代碼可能包含內存泄漏,但與我的第一次測試相比,它在8秒內完成。寫入文件添加了一兩個。你的里程會有所不同。

請注意,-match支持正則表達式,因此您需要轉義正則表達式元字符(如果存在)。

+0

只是試過它對我有什麼,也許應該指定我想要的模式是在多個文件。無論如何,只是測試兩個和沒有寫入,他們給我2分13秒和4分42秒 – Adlis

+0

流媒體閱讀器上的4分鐘?你可以減少選擇文件集嗎? – Matt

+0

另外我想多個文件正在返回。你如何衡量執行時間? – Matt

0

快速寫入文件的方法是使用StreamWriter對象。假設文件在一個文件夾中:

$writer = [System.IO.StreamWriter] "selection.txt" 
$files = gci -Path $path 
$pattern ="Phrase" 
$files | %{gc -Path $_.FullName | select -First 1 | ?{$_ -match $pattern}} | %{$writer.WriteLine($_)} 
+1

我不認爲寫作是問題。此外,如果您的代碼在文件的多行中讀取,即使對新版本中的選擇進行了優化,您也會變得更糟。 – Matt

+0

那麼,如何找到包含該短語的行並通過代碼將其寫入文件片段? – skrubber

+1

我缺少設置內容,任何人都可以添加,但我認爲閱讀表現是問題是我的觀點。 – Matt

1

你可以簡單地把它:

$yoursearch = "PowerShell is cool!" 
get-content "c:\temp\*.*" -TotalCount 1 | where { $_ -ilike "*$yoursearch*"} | select PSPath, @{N="Founded";E={$_}} 

或用於非純粹主義者很短的版本:

gc "c:\temp\*.*" -To 1 | ? { $_ -ilike "*$yoursearch*"} | select PSPath, {$_} 

如果你想導出結果:

$yoursearch = "PowerShell is cool!" 
get-content "c:\temp\*.*" -TotalCount 1 | where { $_ -ilike "*$yoursearch*"} | select PSPath, @{N="Founded";E={$_}} | 
export-csv "c:\temp\yourresult.csv" -notype 

如果你想要一個對於文件的輸入濾波器更好:

Get-ChildItem "c:\temp" -File | 
    Where {$firstrow= (Get-Content $_.FullName -TotalCount 1); $firstrow -ilike "*$yoursearch*"} | 
     Select fullName, @{N="Founded";E={$firstrow}} | 
       Export-Csv "c:\temp\yourresult.csv" -notype 

或短版非純粹主義者:

gci "c:\temp" -File | ? {$r= (gc $_.FullName -TotalCount 1); $r -ilike "*$yoursearch*"} | 
    Select f*, @{N="Founded";E={$r}} | 
     epcsv "c:\temp\yourresult.csv" -notype 

注:-file選項僅在PowerShell中V5(或+),否則使用psiscontainer propertie到其中存在指令

注2:可以使用選擇串的選項-list,SEACH所有文件,但停止時1行成立

$yoursearch = "PowerShell where are you" 
Select-String -Path "c:\temp\*.*" -Pattern $yoursearch -list | select Path, Line | export-csv "C:\temp\result.csv" -NoTypeInformation 
0

一個例子,我會怎麼做會像

Get-ChildItem -Path $ path | Where-Object {$ _。Name -contains「My String」}

這通常是實現這一目標的一種非常快速的方法,但是如果您通過整個C:​​\驅動器進行遞歸操作,那麼無論您將坐在哪裏一分鐘,除非你多線程