2014-01-23 4 views
12

In Powershell, wie die letzte Zeile (oder alle Zeilen), die eine bestimmte Zeichenfolge in einer großen Textdatei (ca. 200000 Zeilen/30 MB) enthält, so schnell wie möglich zu lesen und zu erhalten? Ich verwende:Holen Sie alle Zeilen, die einen String enthalten, in eine riesige Textdatei - so schnell wie möglich?

get-content myfile.txt | select-string -pattern "my_string" -encoding ASCII | select -last 1 

Aber es ist sehr, sehr lang (ca. 16-18 Sekunden). Ich habe Tests ohne das letzte Rohr "select -last 1", aber es ist die gleiche Zeit.

Gibt es einen schnelleren Weg die letzte Vorkommen (oder alle Vorkommen) einer bestimmten Zeichenfolge in riesigen Datei zu bekommen?

Vielleicht ist es die benötigte Zeit ... Oder gibt es eine Möglichkeit, die Datei schneller vom Ende zu lesen, wie ich das letzte Vorkommen wollen? Danke

+3

Der Grund gab es kein ändern Sie, ob Sie an "Select -last 1" weitergeleitet haben oder nicht, weil die gesamte Datei verarbeitet werden muss, um zu wissen, welche "letzte" ist. –

+2

Sie müssen möglicherweise .NET verwenden, um etwas Leistung dort zu haben: [Beginnen, massive Textdatei vom Ende zu lesen] (http://stackoverflow.com/questions/13621225/start-reading-massive-text-file-from-the -Ende). – Neolisk

Antwort

2

Haben Sie versucht mit [System.IO.File]::ReadAllLines();? Diese Methode ist "roher" als die PowerShell-ähnliche Methode, da wir uns direkt an die Microsoft .NET Framework-Typen anschließen.

$Lines = [System.IO.File]::ReadAllLines(); 
[Regex]::Matches($Lines, 'my_string_pattern'); 
+0

Kann bei großen Dateien zu langsam sein oder sogar wegen einer nicht ausreichenden Speicherausnahme abstürzen. – Neolisk

+1

Dieser Benutzer sagte speziell, dass er große Dateien verwendet, warum würden Sie eine Lösung posten, die "stürzt ab, wenn sie mit großen Dateien verwendet wird"? –

+0

wenn ich will, dass regulärer Ausdruck eine ganze Zeile gibt, wo das Muster stimmt, wie das geht [Regex] :: Matches ($ line, 'Database:'); Es sollte geben, wo es Datenbank übereinstimmt: aber es sollte auch Datenbank-Name geben – deepti

26

Try this:

get-content myfile.txt -ReadCount 1000 | 
foreach { $_ -match "my_string" } 

, dass Ihre Datei in Blöcken von 1000 Datensätze auf einmal gelesen werden, und die Spiele in jedem Brocken finden. Dadurch erhalten Sie eine bessere Leistung, da Sie bei der Speicherverwaltung nicht viel CPU-Zeit verschwenden, da jeweils nur 1000 Zeilen in der Pipeline sind.

+1

Das funktionierte großartig auf einem 1.5gb Text-Dump. –

+0

Ist es irgendwie möglich, in der Nähe Linien zurückzugeben? –

1

Haben Sie versucht:

gc myfile.txt | % { if($_ -match "my_string") {write-host $_}} 

Oder können Sie eine "grep" -ähnliche Funktion erstellen:

function grep($f,$s) { 
    gc $f | % {if($_ -match $s){write-host $_}} 
    } 

Dann können Sie einfach Ausgabe: grep $myfile.txt $my_string

Verwandte Themen