Jak zrobić to, co głowa, ogon, więcej, mniej, sed w PowerShell? [Zamknięte]

110

W systemie Windows z użyciem PowerShell, jakie są równoważne polecenia Linuksa na head, tail, more, lessi sed?

Yue Zhang
źródło
plik dziennika jest za duży, około kilku MB. Jest zbyt trudny do wyświetlenia przez notepad.exe.
Yue Zhang
Jeśli używasz notepadjako bazy, sugerowałbym przyjrzenie się alternatywnym edytorom tekstu, istnieje wiele (zarówno bezpłatnych, jak i płatnych) alternatyw. Wszystkie są lepsze od notatnika (choć nie jest to duże wyzwanie).
Richard
możliwy duplikat powłoki PowerShell vs. Unix Shells
manojlds
Mam do czynienia z dużymi plikami i używam / instaluję Vima, który okazuje się znacznie szybszy niż jakiekolwiek inne narzędzie, którego używałem.
sfanjoy

Odpowiedzi:

176

Get-Content(alias:) gcjest typową opcją odczytu pliku tekstowego. Następnie możesz dalej filtrować:

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

Działa to wystarczająco dobrze w przypadku małych plików, większe (więcej niż kilka MiB) są prawdopodobnie nieco powolne.

W PowerShell Community Extensions zawiera kilka apletów poleceń dla wyspecjalizowanych plików rzeczy (np Get-FileTail).

Joey
źródło
3
Święta krowa, to jest maksymalne wykorzystanie mojego procesora do zrobienia -last 21GB CSV. Napój gorący: ☕
mlissner
9
@mlissner: Jeśli korzystasz z PowerShell v3, możesz użyć Get-Content -Tail 2zamiast tego. To zdecydowanie szybsze.
Joey,
gc log.txt | %{ $_ -replace '\d+', '($0)' } # sedw rzeczywistości nie jest to w pełni narzędzie sed, ponieważ nie przywraca zawartości. Potrzebuje zestawu treści.
Artem
3
@Neil, -Lastjest powolny z tego samego powodu, awkbyłby powolny w przypadku tego samego zadania: najpierw musi całkowicie zużywać strumień. Dlatego Get-Content -Tailistnieje. I nie ma, headponieważ nie pasuje do konwencji nazewnictwa, a jego cel już służy Select-Item.
Joey
3
@neil @joey Mają alias dla -head. Zobacz moją odpowiedź stackoverflow.com/a/41626586/1081043
wisbucky
53

Oto wbudowane sposoby wykonywania headi tail. Nie używaj potoków, ponieważ jeśli masz duży plik, będzie on bardzo wolny. Korzystanie z tych wbudowanych opcji będzie niezwykle szybkie, nawet w przypadku dużych plików.

gc log.txt -head 10 
gc log.txt -tail 10
gc log.txt -tail 10 -wait # equivalent to tail -f
wisbucky
źródło
ale komentarz Joey'a wydaje się wskazywać na coś zupełnie przeciwnego! skąd mam wiedzieć, komu ufać lub która (wbudowana) metoda jest najbardziej wydajna?
NH.
2
@NH Moja odpowiedź jest zgodna z komentarzem Joey'a. Jego komentarz mówi: „-Last is slow ... Dlatego istnieje Get-Content -Tail”. | select -lastużywa rur. Używam -tailbez rur. Ale jeśli kiedykolwiek znajdziesz dwie sprzeczne odpowiedzi, prawdopodobnie możesz zaufać osobie o znacznie wyższej reputacji. Możesz też po prostu wypróbować obie metody na dużym pliku. Będzie to bardzo oczywiste w przypadku dużego pliku.
wisbucky
Rozumiem. Przepraszam, musiałem się pomylić, kiedy pierwszy raz czytałem te posty.
NH.
8

more.exeistnieje w systemie Windows, porty lessmożna łatwo znaleźć (a rozszerzenie społeczności programu PowerShell , PSCX, zawiera jeden).

PowerShell tak naprawdę nie zapewnia żadnej alternatywy dla oddzielnych programów, ale w przypadku danych strukturalnych Out-Gridmoże być pomocny.

Headi Tailoba mogą być emulowane przy Select-Objectużyciu odpowiednio parametrów -Firsti -Last.

Sedfunkcje są dostępne, ale mają inną strukturę. Opcje filtrowania są dostępne w Where-Object(lub przez Foreach-Objectoraz w niektórych stanach dla zakresów). Inne, przekształcające operacje można wykonać za pomocą Select-Objecti Foreach-Object.

Jednak gdy PowerShell przekazuje obiekty (.NET) - z całą ich typowaną strukturą, np. daty pozostają DateTimeinstancjami - a nie tylko ciągami, które każda komenda musi sama przeanalizować, wiele sedinnych programów jest zbędnych.

Richard
źródło
Znakomity. Wydaje się, że gc nie obsługuje wejścia potoku. kiedy chcę filtrować dane wyjściowe polecenia, używam „... exe ... | select-object -first 20 | select-object -last 1”
A117
2

„-TotalCount” w tym przypadku odpowiada dokładnie tak samo, jak „-head”. Musisz użyć -TotalCount lub -head, aby uruchomić polecenie w ten sposób. Ale -TotalCount jest mylący - nie działa w RZECZYWISTYM podając ŻADNE liczby ...

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

Powyższy skrypt, przetestowany w PS 5.1, jest tą samą odpowiedzią, co poniżej ...

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

Więc po prostu użyj już '-head 25'!

Patrick Burwell
źródło
Cześć @Patrick, witaj w Stack Overflow! Dziękujemy za próbę odpowiedzi na to pytanie. Czy mógłbyś podać bardziej szczegółowe wyjaśnienie? Nie jest jasne, czy próbujesz zaproponować rozwiązanie, czy po prostu chcesz skomentować problem.
Rocío García Luque
To był komentarz, a także frustracja. „-TotalCount” nic nie robi ”-Head” już nie robi. Więc czy ktoś WIEDZIE, jak uzyskać TotalCount?
Patrick Burwell
Przeczytaj jeszcze raz ... dodałem DO odpowiedzi i wyjaśniłem, co działa ...
Patrick Burwell
1

Jeśli chcesz przeszukiwać duże (lub małe) pliki dziennika w systemie Windows, najlepszym narzędziem, jakie znalazłem, jest bezpłatny Log Parser 2.2 firmy Microsoft . Możesz zadzwonić do tego z PowerShell, jeśli chcesz, a on wykona za Ciebie wszystkie ciężkie prace, a także bardzo szybko.

Co byłoby fajne
źródło
w każdym razie dzięki, Moje środowisko to Win2k8R2, którego nie ma w wymaganiach systemowych Log Parser2.2
Yue Zhang
0

Mam kilka lepszych rozwiązań:

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
źródło
-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

Przy okazji, nie otrzymujesz wszystkich błędów z kodem pushpop, twój kod działa tylko z opcją "sed". Cała reszta ignoruje wszystko poza gc i ścieżką.

Patrick Burwell
źródło