Tengo un archivo con aproximadamente 1000 líneas. Quiero la parte de mi archivo después de la línea que coincide con mi declaración grep.
Es decir:
$ cat file | grep 'TERMINATE' # It is found on line 534
Entonces, quiero el archivo de la línea 535 a la línea 1000 para su posterior procesamiento.
¿Cómo puedo hacer eso?
grep 'TERMINATE' file
grep
la interfaz de entrada estándar para leer datos, en lugar de tener que aprender a qué interruptor aplicargrep
, ysed
, yawk
, ypandoc
, yffmpeg
etc. cuando queremos leer de un archivo Ahorra tiempo porque no tenemos que aprender un nuevo interruptor cada vez que queremos hacer lo mismo: leer de un archivo.grep 'TERMINATE' < file
. Tal vez haga que la lectura sea un poco más difícil, pero esto es un script de shell, por lo que siempre será un problema :)Respuestas:
Lo siguiente imprimirá la coincidencia de línea
TERMINATE
hasta el final del archivo:Explicado:
-n
deshabilita el comportamiento predeterminadosed
de imprimir cada línea después de ejecutar su secuencia de comandos,-e
indicando una secuencia de comandos parased
,/TERMINATE/,$
es una selección de rango de dirección (línea) que significa la primera línea que coincide con laTERMINATE
expresión regular (como grep) al final del archivo ($
) , yp
es el comando de impresión que imprime la línea actual.Esto se imprimirá desde la línea que sigue a la línea coincidente
TERMINATE
hasta el final del archivo:(DESPUÉS de la línea coincidente a EOF, SIN incluir la línea coincidente)
Explicado:
1,/TERMINATE/
es una selección de rango de dirección (línea) que significa la primera línea para la entrada a la primera línea que coincide con laTERMINATE
expresión regular, yd
es el comando de eliminación que elimina la línea actual y salta a la siguiente línea. Comosed
el comportamiento predeterminado es imprimir las líneas, imprimirá las líneas desdeTERMINATE
el final de la entrada.Editar:
Si quieres las líneas antes
TERMINATE
:Y si desea ambas líneas antes y después
TERMINATE
en 2 archivos diferentes en una sola pasada:Los archivos antes y después contendrán la línea con terminación, por lo que para procesar cada uno debe usar:
Edit2:
SI no desea codificar los nombres de archivo en el script sed, puede:
Pero luego debe escapar del
$
significado de la última línea para que el shell no intente expandir la$w
variable (tenga en cuenta que ahora usamos comillas dobles alrededor del script en lugar de comillas simples).Olvidé decir que la nueva línea es importante después de los nombres de archivo en el script para que sed sepa que los nombres de archivo terminan.
Editar: 2016-0530
Sébastien Clément preguntó: "¿Cómo reemplazarías el hardcoded
TERMINATE
por una variable?"Haría una variable para el texto coincidente y luego lo haría de la misma manera que en el ejemplo anterior:
para usar una variable para el texto coincidente con los ejemplos anteriores:
Los puntos importantes sobre la sustitución de texto con variables en estos casos son:
$variablename
) encerradas ensingle quotes
['
] no se "expandirán" pero las variables dentro dedouble quotes
["
] sí. Por lo tanto, debe cambiar todosingle quotes
adouble quotes
si contienen texto que desea reemplazar con una variable.sed
rangos también contienen una$
y son seguidos inmediatamente por una carta como:$p
,$d
,$w
. También se verá como las variables que ser ampliado, por lo que tiene que escapar de esos$
personajes con una barra invertida [\
] como:\$p
,\$d
,\$w
.fuente
sed -e "1,/$matchtext/d"
no funciona cuando$matchtext
ocurre en la primera línea. Tuve que cambiarlo ased -e "0,/$matchtext/d"
.Como una aproximación simple, podría usar
que greps
TERMINATE
y salidas de hasta 100000 líneas después de esa línea.De la página man
fuente
file
lugar:grep -A$(cat file | wc -l) TERMINATE file
Una herramienta para usar aquí es awk:
Como funciona esto:
Las otras soluciones pueden consumir mucha memoria si las usa en archivos muy grandes.
fuente
cat file | awk 'BEGIN{ found=0} /###/{found=found+1} {if (found<2) print }'
cat
.awk
es perfectamente capaz de tomar uno o más nombres de archivo como argumentos. Ver también stackoverflow.com/questions/11710552/useless-use-of-catSi entiendo tu pregunta correctamente, quieres las líneas después
TERMINATE
, sin incluir la líneaTERMINATE
.awk
puede hacer esto de una manera simple:Explicación:
if(found) print
) no imprimirá nada para comenzar.Esto imprimirá todas las líneas después de la línea
TERMINATE
.Generalización:
Ejemplo:
Explicación:
found
está configurada.found=1
para que se impriman las siguientes líneas. Tenga en cuenta que esta verificación se realiza después de la impresión real para excluir la línea de inicio del resultado.Notas:
BEGIN{found=0}
al comienzo de la expresión awk.fuente
{if(found) print}
es un poco anti-patrón en awk, es más idiomático reemplazar el bloque con solofound
ofound;
si necesita otro filtro después.awk '{if(found) print} /TERMINATE/{found=1}' your_file
conawk 'found; /TERMINATE/{found=1}' your_file
, ambos deberían hacer lo mismo.Utilice la expansión de parámetros bash de la siguiente manera:
fuente
printf
o asegurarse de saber exactamente a qué está pasandoecho
).grep -A 10000000 'TERMINAR' archivo
fuente
Hay muchas formas de hacerlo con
sed
oawk
:Esto busca
TERMINATE
en su archivo e imprime desde esa línea hasta el final del archivo.Este es exactamente el mismo comportamiento que
sed
.En caso de que sepa el número de la línea desde la que desea comenzar a imprimir, puede especificarlo junto con
NR
(número de registro, que finalmente indica el número de la línea):Ejemplo
fuente
more +7 file
Si por alguna razón desea evitar el uso de sed, lo siguiente imprimirá la coincidencia de línea
TERMINATE
hasta el final del archivo:y lo siguiente se imprimirá desde la siguiente coincidencia de línea
TERMINATE
hasta el final del archivo:Se necesitan 2 procesos para hacer lo que sed puede hacer en un proceso, y si el archivo cambia entre la ejecución de grep y tail, el resultado puede ser incoherente, por lo que recomiendo usar sed. Además, si el archivo no contiene
TERMINATE
, el primer comando falla.fuente
Alternativas a la excelente
sed
respuesta de jfgagne, y que no incluyen la línea correspondiente:awk '/TERMINATE/ {y=1;next} y'
( https://stackoverflow.com/a/18166628 )awk '/TERMINATE/ ? c++ : c'
( https://stackoverflow.com/a/23984891 )perl -ne 'print unless 1 .. /TERMINATE/'
( https://stackoverflow.com/a/18167194 )fuente
Esta podría ser una forma de hacerlo. Si sabe en qué línea del archivo tiene su palabra grep y cuántas líneas tiene en su archivo:
grep -A466 'TERMINAR' archivo
fuente
grep
ni siquiera se requiere; puedes usartail -n $NUM
, así que esto no es realmente una respuesta.sed es una herramienta mucho mejor para el trabajo: archivo sed -n '/ re /, $ p'
donde re es regexp.
Otra opción es la bandera de grep --after-context. Debe pasar un número para finalizar, el uso de wc en el archivo debería proporcionar el valor correcto para detenerse. Combina esto con -n y tu expresión de coincidencia.
fuente
Estos imprimirán todas las líneas desde la última línea encontrada "TERMINAR" hasta el final del archivo:
fuente
grep
que pueda alimentarlotail
es un antipatrón derrochador. Encontrar la coincidencia e imprimir hasta el final del archivo (o, por el contrario, imprimir y detener en la primera coincidencia) se realiza eminentemente con las herramientas de expresión regular normales y esenciales. Lo masivogrep | tail | sed | awk
también es en sí mismo un uso inútil ygrep
masivo de amigos .tail
y realice la tarea en la herramienta más capaz. De todos modos, el título dice claramente "primer partido".