Wie macht man das, was Kopf, Schwanz, mehr, weniger, sed in Powershell tun? [geschlossen]

108

Unter Windows mit Powershell, was die entsprechenden Befehle an Linux sind head, tail, more, lessund sed?

Yue Zhang
quelle
Die Protokolldatei ist zu groß, etwa mehrere MByte. Es ist zu schwer, von notepad.exe zu sehen.
Yue Zhang
Wenn Sie notepadals Basis verwenden, würde ich vorschlagen, nach alternativen Texteditoren zu suchen. Es gibt viele (sowohl kostenlose als auch kostenpflichtige) Alternativen. Alle sind dem Notizblock überlegen (obwohl das keine große Herausforderung ist).
Richard
Mögliches Duplikat von PowerShell vs. Unix Shells
Manojlds
Ich beschäftige mich mit großen Dateien und verwende / installiere Vim, was sich als viel schneller herausstellt als jedes andere Tool, das ich verwendet habe.
sfanjoy

Antworten:

174

Get-Content(Alias ​​:) gcist Ihre übliche Option zum Lesen einer Textdatei. Sie können dann weiter filtern:

gc log.txt | select -first 10 # head
gc -TotalCount 10 log.txt     # also head
gc log.txt | select -last 10  # tail
gc -Tail 10 log.txt           # also tail (since PSv3), also much faster than above option
gc log.txt | more             # or less if you have it installed
gc log.txt | %{ $_ -replace '\d+', '($0)' }         # sed

Dies funktioniert gut genug für kleine Dateien, größere (mehr als ein paar MiB) sind wahrscheinlich etwas langsam.

Die PowerShell-Community-Erweiterungen enthalten einige Cmdlets für spezielle Dateien (z. B. Get-FileTail).

Joey
quelle
3
Heilige Kuh, das ist das Maximum meiner CPU, um -last 2eine 1-GB-CSV- Datei zu erstellen . Heißgetränk: ☕
mlissner
9
@mlissner: Wenn Sie mit PowerShell v3 arbeiten, können Sie Get-Content -Tail 2stattdessen verwenden. Das geht definitiv schneller.
Joey
gc log.txt | %{ $_ -replace '\d+', '($0)' } # sedDas ist eigentlich nicht das Sed-Tool, da es den Inhalt nicht zurücksetzt. Es braucht Set-Content.
Artyom
3
@Neil, -Lastist langsam aus dem gleichen Grund awkwäre langsam für die gleiche Aufgabe: Es muss zuerst den Stream komplett verbrauchen. Deshalb Get-Content -Tailgibt es. Und es gibt keine, headweil es nicht in die Namenskonventionen passt und sein Zweck bereits erfüllt ist Select-Item.
Joey
3
@neil @joey Sie haben einen Alias ​​für -head. Siehe meine Antwort stackoverflow.com/a/41626586/1081043
wisbucky
51

Hier sind die integrierten Möglichkeiten headund tail. Verwenden Sie keine Pipes, denn wenn Sie eine große Datei haben, ist diese extrem langsam. Die Verwendung dieser integrierten Optionen ist selbst bei großen Dateien extrem schnell.

gc log.txt -head 10 
gc log.txt -tail 10
gc log.txt -tail 10 -wait # equivalent to tail -f
wisbucky
quelle
aber Joeys Kommentar scheint das genaue Gegenteil anzuzeigen! Woher weiß ich, wem ich vertrauen soll oder welche (integrierte) Methode am effizientesten ist?
NH.
2
@NH Meine Antwort stimmt mit Joeys Kommentar überein. Sein Kommentar sagt "-Last ist langsam ... Deshalb gibt es Get-Content -Tail." | select -lastverwendet Rohre. Ich benutze -tailohne Rohre. Wenn Sie jedoch jemals zwei widersprüchliche Antworten finden, können Sie der Person mit einem viel höheren Ruf wahrscheinlich vertrauen. Sie können die beiden Methoden auch einfach für eine große Datei ausprobieren. Bei einer großen Datei ist dies sehr offensichtlich.
wisbucky
Verstanden. Entschuldigung, ich muss verwirrt gewesen sein, als ich die Beiträge zum ersten Mal gelesen habe.
NH.
8

more.exeexistiert unter Windows, Ports von lesssind leicht zu finden (und die PowerShell Community Extensions , PSCX, enthalten einen).

PowerShell bietet für beide keine Alternative zu separaten Programmen, aber für strukturierte Daten Out-Gridkann dies hilfreich sein.

Headund Tailkönnen beide mit Select-Objectden Parametern -Firstund emuliert werden -Last.

SedFunktionen sind alle verfügbar, aber ziemlich unterschiedlich strukturiert. Die Filteroptionen sind in Where-Object(oder via Foreach-Objectund einigen Status für Bereiche) verfügbar . Andere, transformierende Operationen können mit Select-Objectund durchgeführt werden Foreach-Object.

Wenn PowerShell jedoch (.NET) Objekte übergibt - mit all ihrer typisierten Struktur, z. Datumsangaben bleiben DateTimeInstanzen - und nicht nur Zeichenfolgen, die jeder Befehl selbst analysieren muss. Viele seddieser Programme sind redundant.

Richard
quelle
Brillant. gc scheint die Pipe-Eingabe nicht zu unterstützen. Wenn ich die Ausgabe eines Befehls filtern möchte, verwende ich "... exe ... | select-object -first 20 | select-object -last 1"
A117
2

"-TotalCount" antwortet in diesem Fall genau wie "-head". Sie müssen -TotalCount oder -head verwenden, um den Befehl so auszuführen. Aber - TotalCount ist irreführend - es funktioniert nicht, wenn Sie tatsächlich irgendwelche Zählungen erhalten ...

gc -TotalCount 25 C:\scripts\logs\robocopy_report.txt

Das obige Skript, das in PS 5.1 getestet wurde, ist die gleiche Antwort wie unten ...

gc -head 25 C:\scripts\logs\robocopy_report.txt

Also dann benutze einfach '-head 25 "schon!

Patrick Burwell
quelle
Hallo @Patrick, willkommen bei Stack Overflow! Vielen Dank, dass Sie versucht haben, diese Frage zu beantworten. Können Sie uns bitte eine ausführlichere Erklärung geben? Es ist unklar, ob Sie versuchen, eine Lösung anzubieten oder nur einen Kommentar zum Problem hinzuzufügen.
Rocío García Luque
Es war ein Kommentar und auch eine Frustration. '-TotalCount "macht nichts" -Head "tut es noch nicht. Weiß also jemand, wie man einen TotalCount bekommt?
Patrick Burwell
Lesen Sie es noch einmal ... Ich fügte der Antwort hinzu und stellte klar, was funktioniert ...
Patrick Burwell
1

Wenn Sie große (oder kleine) Protokolldateien unter Windows abfragen müssen, ist das beste Tool, das ich gefunden habe, der kostenlose Log Parser 2.2 von Microsoft . Sie können es von PowerShell aus aufrufen, wenn Sie möchten, und es erledigt das ganze schwere Heben für Sie und auch sehr schnell.

Was wäre cool
quelle
Trotzdem danke, meine Umgebung ist Win2k8R2, die nicht in den Systemanforderungen von Log Parser2.2
Yue Zhang
0

Ich habe einige bessere Lösungen:

gc log.txt -ReadCount 5 | %{$_;throw "pipeline end!"} # head
gc log.txt | %{$num=0;}{$num++;"$num $_"}             # cat -n
gc log.txt | %{$num=0;}{$num++; if($num -gt 2 -and $num -lt 7){"$num $_"}} # sed
Yue Zhang
quelle
-1
$Push_Pop = $ErrorActionPreference #Suppresses errors
$ErrorActionPreference = SilentlyContinue #Suppresses errors
#Script
    #gc .\output\*.csv -ReadCount 5 | %{$_;throw "pipeline end!"} # head
    #gc .\output\*.csv | %{$num=0;}{$num++;"$num $_"}             # cat -n
    gc .\output\*.csv | %{$num=0;}{$num++; if($num -gt 2 -and $num -lt 7){"$num $_"}} # sed
#End Script 
$ErrorActionPreference = $Push_Pop #Suppresses errors

Sie erhalten nicht alle Fehler mit dem Pushpop-Code BTW, Ihr Code funktioniert nur mit der Option "sed". Der Rest ignoriert alles andere als gc und path.

Patrick Burwell
quelle