Come fare cosa fanno head, tail, more, less, sed in Powershell? [chiuso]


109

Su Windows, utilizzando PowerShell, quali sono i comandi equivalenti a Linux di head, tail, more, lesse sed?


Il file di log è troppo grande, circa diversi MByte. È troppo difficile da visualizzare con notepad.exe.
Yue Zhang

Se stai usando notepadcome base, ti suggerirei di guardare editor di testo alternativi, ci sono molte alternative (sia gratuite che a pagamento). Tutti sono superiori al blocco note (anche se non è una grande sfida).
Richard

possibile duplicato di PowerShell vs Unix Shells
manojlds

Mi occupo di file di grandi dimensioni e uso / installo Vim che si rivela molto più veloce di qualsiasi altro strumento che ho usato.
sfanjoy

Risposte:


174

Get-Content(alias:) gcè la tua solita opzione per leggere un file di testo. È quindi possibile filtrare ulteriormente:

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

Funziona abbastanza bene per file piccoli, quelli più grandi (più di pochi MiB) sono probabilmente un po 'lenti.

Le estensioni della community di PowerShell includono alcuni cmdlet per elementi di file specializzati (ad esempio Get-FileTail).


3
Holy cow, this is maxing out my CPU to do a -last 2on a 1GB CSV. Bevanda calda: ☕
mlissner

9
@mlissner: se sei su PowerShell v3 puoi usare Get-Content -Tail 2invece. È decisamente più veloce.
Joey

gc log.txt | %{ $_ -replace '\d+', '($0)' } # sedquesto non è in realtà completamente lo strumento sed poiché non rimette il contenuto. Ha bisogno di Set-Content.
Artyom

3
@Neil, -Lastè lento per lo stesso motivo awksarebbe lento per lo stesso compito: deve prima consumare completamente lo stream. Ecco perché Get-Content -Tailesiste. E non c'è headperché non rientra nelle convenzioni di denominazione e il suo scopo è già servito da Select-Item.
Joey

3
@neil @joey Hanno un alias per -head. Vedere la mia risposta stackoverflow.com/a/41626586/1081043
wisbucky

52

Ecco i modi predefiniti per fare heade tail. Non usare pipe perché se hai un file di grandi dimensioni, sarà estremamente lento. L'utilizzo di queste opzioni integrate sarà estremamente veloce anche per file di grandi dimensioni.

gc log.txt -head 10 
gc log.txt -tail 10
gc log.txt -tail 10 -wait # equivalent to tail -f

ma il commento di Joey sembra indicare l'esatto contrario! come faccio a sapere di chi fidarmi o di quale metodo (integrato) è più efficiente?
NH.

2
@NH La mia risposta è in accordo con il commento di Joey. Il suo commento dice "-Last is slow ... Ecco perché esiste Get-Content -Tail." | select -lastusa i tubi. Sto usando -tailsenza tubi. Ma se trovi mai due risposte contrastanti, potresti probabilmente fidarti della persona con una reputazione molto più alta. Inoltre, puoi semplicemente provare i due metodi su un file di grandi dimensioni. Sarà molto ovvio su un file di grandi dimensioni.
wisbucky

Fatto. Scusa, devo essere stato confuso la prima volta che ho letto i post.
NH.

8

more.exeesiste su Windows, le porte di lesssono facilmente reperibili (e le estensioni della community di PowerShell , PSCX, ne includono una).

PowerShell non fornisce alcuna alternativa a programmi separati per nessuno dei due, ma per i dati strutturati Out-Gridpuò essere utile.

Heade Tailpossono essere entrambi emulati Select-Objectutilizzando rispettivamente i parametri -Firste -Last.

Sedle funzioni sono tutte disponibili ma strutturate in modo piuttosto diverso. Le opzioni di filtro sono disponibili in Where-Object(o tramite Foreach-Objecte alcuni stati per gli intervalli). Altre operazioni di trasformazione possono essere eseguite con Select-Objecte Foreach-Object.

Tuttavia, quando PowerShell passa (.NET) oggetti, con tutta la loro struttura tipizzata, ad es. le date rimangono DateTimeistanze - piuttosto che solo stringhe, di cui ogni comando ha bisogno per analizzare se stesso, molti sedaltri programmi simili sono ridondanti.


Brillante. gc non sembra supportare l'input di pipe. quando voglio filtrare l'output di un comando, sto usando "... exe ... | select-object -first 20 | select-object -last 1"
A117

2

"-TotalCount" in questa istanza risponde esattamente come "-head". Devi usare -TotalCount o -head per eseguire il comando in questo modo. Ma -TotalCount è fuorviante - non funziona REALMENTE dandoti ALCUN conteggio ...

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

Lo script sopra, testato in PS 5.1 è la STESSA risposta come sotto ...

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

Quindi usa già '-head 25 "!


Ciao @Patrick, benvenuto in Stack Overflow! Grazie per aver cercato di rispondere a questa domanda, potresti fornire una spiegazione più dettagliata? Non è chiaro se stai cercando di offrire una soluzione o semplicemente di aggiungere qualche commento sul problema.
Rocío García Luque

Era un commento e anche una frustrazione. "-TotalCount" non fa nulla "-Head" non lo fa già. Quindi qualcuno sa come ottenere un TotalCount?
Patrick Burwell

Leggilo di nuovo ... ho aggiunto alla risposta e chiarito cosa funziona ...
Patrick Burwell

1

Se è necessario eseguire query su file di registro grandi (o piccoli) su Windows, lo strumento migliore che ho trovato è il Log Parser 2.2 gratuito di Microsoft . Puoi chiamarlo da PowerShell se vuoi e farà tutto il lavoro pesante per te, e anche molto velocemente.


grazie comunque, il mio ambiente è Win2k8R2 che non è nei requisiti di sistema di Log Parser2.2
Yue Zhang

0

Ho alcune soluzioni migliori:

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

-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

Non ottieni tutti gli errori con il codice pushpop BTW, il tuo codice funziona solo con l'opzione "sed". Tutto il resto ignora tutto tranne gc e path.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.