¿Cómo hacer lo que hacen head, tail, more, less, sed en Powershell? [cerrado]

109

En las ventanas, uso de PowerShell, ¿cuáles son los comandos equivalentes a Linux head, tail, more, lessy sed?

Yue Zhang
fuente
El archivo de registro es demasiado grande, alrededor de varios MBytes. Es demasiado difícil de ver por notepad.exe.
Yue Zhang
Si lo está utilizando notepadcomo base, le sugiero que busque editores de texto alternativos, hay muchas alternativas (gratuitas y de pago). Todos son superiores al bloc de notas (aunque eso no es un gran desafío).
Richard
posible duplicado de PowerShell vs Unix Shells
manojlds
Trato con archivos grandes y uso / instalo Vim, que resulta mucho más rápido que cualquier otra herramienta que haya usado.
sfanjoy

Respuestas:

174

Get-Content(alias:) gces su opción habitual para leer un archivo de texto. A continuación, puede filtrar más:

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

Esto funciona bastante bien para archivos pequeños, los más grandes (más de unos pocos MiB) son probablemente un poco lentos.

Las extensiones de la comunidad de PowerShell incluyen algunos cmdlets para archivos especializados (por ejemplo, Get-FileTail).

Joey
fuente
3
Santo cielo, esto está maximizando mi CPU para hacer un -last 2CSV de 1GB. Bebida caliente: ☕
mlissner
9
@mlissner: si está en PowerShell v3, puede usar Get-Content -Tail 2en su lugar. Definitivamente es más rápido.
Joey
gc log.txt | %{ $_ -replace '\d+', '($0)' } # sedque en realidad no es completamente la herramienta sed, ya que no devuelve el contenido. Necesita Set-Content.
Artyom
3
@Neil, -Lastes lento por la misma razón awkque sería lento para la misma tarea: primero tiene que consumir el flujo por completo. Por eso Get-Content -Tailexiste. Y no hay headporque no encaja en las convenciones de nomenclatura, y su propósito ya está cumplido Select-Item.
Joey
3
@neil @joey Tienen un alias para -head. Vea mi respuesta stackoverflow.com/a/41626586/1081043
wisbucky
52

Aquí están las formas integradas de hacer heady tail. No use tuberías porque si tiene un archivo grande, será extremadamente lento. El uso de estas opciones integradas será extremadamente rápido incluso para archivos grandes.

gc log.txt -head 10 
gc log.txt -tail 10
gc log.txt -tail 10 -wait # equivalent to tail -f
Wisbucky
fuente
¡pero el comentario de Joey parece indicar exactamente lo contrario! ¿Cómo sé en quién confiar o qué método (integrado) es más eficiente?
NH.
2
@NH Mi respuesta está de acuerdo con el comentario de Joey. Su comentario dice "-Last is slow ... Es por eso que Get-Content -Tail existe". | select -lastutiliza tuberías. Estoy usando -tailsin tuberías. Pero si alguna vez encuentra dos respuestas contradictorias, probablemente podría confiar en la persona con una reputación mucho más alta. Además, puede simplemente probar los dos métodos en un archivo grande. Será muy obvio en un archivo grande.
wisbucky
Entendido. Lo siento, debí haberme confundido la primera vez que leí las publicaciones.
NH.
8

more.exeexiste en Windows, los puertos de lessse encuentran fácilmente (y las Extensiones de la comunidad de PowerShell , PSCX, incluyen una).

PowerShell realmente no ofrece ninguna alternativa a los programas separados para ninguno de los dos, pero para los datos estructurados Out-Gridpuede ser útil.

Heady Tailambos pueden emularse Select-Objectusando los parámetros -Firsty -Lastrespectivamente.

Sedtodas las funciones están disponibles pero estructuradas de manera bastante diferente. Las opciones de filtrado están disponibles en Where-Object(o vía Foreach-Objecty algún estado para rangos). Se pueden realizar otras operaciones de transformación con Select-Objecty Foreach-Object.

Sin embargo, a medida que PowerShell pasa objetos (.NET), con toda su estructura escrita, por ejemplo. las fechas siguen siendo DateTimeinstancias, en lugar de solo cadenas, que cada comando necesita analizar por sí mismo, muchos de sedestos programas y otros son redundantes.

Ricardo
fuente
Brillante. gc no parece admitir la entrada de tubería. cuando quiero filtrar la salida de un comando, estoy usando "... exe ... | select-object -first 20 | select-object -last 1"
A117
2

"-TotalCount" en este caso responde exactamente como "-head". Tienes que usar -TotalCount o -head para ejecutar el comando de esa manera. Pero -TotalCount es engañoso - no funciona REALMENTE dándote NINGÚN recuento ...

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

El script anterior, probado en PS 5.1 es la MISMA respuesta que a continuación ...

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

¡Entonces solo usa '-head 25 "ya!

Patrick Burwell
fuente
Hola @Patrick, ¡bienvenido a Stack Overflow! Gracias por intentar responder a esta pregunta, ¿podría proporcionar una explicación más detallada? No está claro si está tratando de ofrecer una solución o simplemente agregar algún comentario sobre el problema.
Rocío García Luque
Fue un comentario y también una frustración. '-TotalCount "no hace nada" -Head "aún no lo hace. Entonces, ¿alguien SABE cómo obtener un TotalCount?
Patrick Burwell
Léelo de nuevo ... agregué A la respuesta y aclaré lo que funciona ...
Patrick Burwell
1

Si necesita consultar archivos de registro grandes (o pequeños) en Windows, la mejor herramienta que he encontrado es Log Parser 2.2 gratuito de Microsoft . Puede llamarlo desde PowerShell si lo desea y hará todo el trabajo pesado por usted, y muy rápido también.

¿Qué sería genial?
fuente
gracias de todos modos, Mi entorno es Win2k8R2 que no está en los requisitos del sistema de Log Parser2.2
Yue Zhang
0

Tengo algunas mejores soluciones:

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
fuente
-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

No obtienes todos los errores con el código pushpop Por cierto, tu código solo funciona con la opción "sed". Todo el resto ignora todo menos gc y path.

Patrick Burwell
fuente