grep --before-context 5
muestra 5 líneas antes del partido.
Quiero mostrar todo antes del partido.
Hacerlo grep --before-context 99999999
funcionaría pero no es muy ... profesional.
¿Cómo mostrar todo el archivo hasta el partido?
grep --before-context 5
muestra 5 líneas antes del partido.
Quiero mostrar todo antes del partido.
Hacerlo grep --before-context 99999999
funcionaría pero no es muy ... profesional.
¿Cómo mostrar todo el archivo hasta el partido?
Respuestas:
Sed es mejor para eso.
Solo haz:
sed '/PATTERN/q' FILE
Funciona así:
Para cada línea, buscamos si coincide /PATTERN
:
Esta es la solución más eficiente, porque tan pronto como se ve PATTERN
, se cierra. Sin q
, sed continuaría leyendo el resto del archivo y no haría nada con él. Para archivos grandes puede hacer la diferencia.
Este truco también se puede usar para emular head
:
sed 10q FILE
sed '/PATTERN/Q' FILE
omitirá la línea coincidente. Q
es una extensión GNU, por lo que no funcionará con ningún sed.
sed
puede reemplazar la mayor parte de la funcionalidad de grep.
sed -n '1,/<pattern>/ p' <file>
Esto significa imprimir desde la primera línea hasta que el patrón coincida.
Un par de ejemplos de rango
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
imprimir hasta e incluyendo el partido:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
imprimir hasta PERO SIN incluir el partido:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
Es genial pero afaik específico de GNU, sed -n '/pattern/!p;//q'
sería más portátil.
!
se p
aplica a las líneas que no coinciden pattern
, pero luego //q
me confunde ...
//
significa "expresión regular anterior" (pensé que significaba "coincidir con la cadena vacía"). Creo que una versión más corta de la misma solución es sed -n '/pattern/q;p
:?
Los siguientes grep
métodos puros de GNU no son eficientes.
Busque todo hasta la primera instancia de la cadena " foo " en la barra de archivos , utilizando tres grep
s:
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
Coincidencia hasta la última instancia de " foo ":
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
Nota: los detalles sobre el último grep
se pueden encontrar en: Regex (grep) para la búsqueda multilínea necesaria .
grep
s (+ pcre) cuando se trata simplemente de ejecutar una sola sed
invocación: sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'
??
sed
código parece tener su propia respuesta, o podría agregarse a uno de los otros. Re 7 grep
s: Porque no hubo grep
respuesta ... (además, la respuesta ayuda a mostrar por qué no)
Agregando a la respuesta de Mikel arriba ...
Para imprimir todas las líneas hasta, pero sin incluir , la primera línea que FILE
contiene PATTERN
, intente:
sed '/.*PATTERN.*/{s///;q;}' FILE
Esto coincide con la línea completa que contiene el patrón, lo reemplaza con una línea en blanco y luego se cierra sin procesar el resto del archivo.
Posdata:
La forma más fácil / clara que se me ocurrió para evitar imprimir una nueva línea adicional al final (sin involucrar a otra herramienta), fue ejecutar sed nuevamente y eliminar la nueva línea final:
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
... y dado que ahora estamos eliminando esa línea de todos modos, nuestro trabajo anterior es redundante y podemos simplificarlo para:
sed '/PATTERN/q' FILE | sed '$d'
sed
invocación.
tcsh
y un bash
alias, que necesita para asegurarse de que tenía una solución de una línea relativamente concisa que funcionaba tanto en estándar como en GNU sed
(para portabilidad); todos los requisitos que su contribución bien pudo haber cumplido. Como alguien que usa sed
muy raramente, mi requisito más importante era algo que pudiera entender rápidamente cuando quiero editarlo fácilmente o cambiar su propósito dentro de años.
Para las personas que eligen recordar solo las herramientas básicas en el trabajo diario y están dispuestas a aceptar soluciones menos elegantes y menos eficientes:
head -n $(grep -n pattern filename | cut -d: -f1) filename
Si este comando es para un script, buscaré soluciones más elegantes (y posiblemente eficientes). Si este es un comando de una sola vez o un script de descarte, no me importa
También puedes usar uno de los siguientes
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
o
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
o
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
La primera opción es muy similar a lo que sugirió el OP, solo se asegura de que muestre suficientes líneas antes del contexto contando las líneas en el archivo
La segunda opción busca el número de línea de la primera coincidencia (también puede cambiar eso cambiando la 'cabeza' interna) y luego usa cabeza en ese número
La última opción reemplaza todas las líneas nuevas con la coincidencia y luego reemplaza dos coincidencias adyacentes con una nueva línea. El resultado de esto es una línea para cada bloque de texto entre dos coincidencias. Después de eso, usa 'head' para elegir la primera línea (que disminuye el bloque de texto hasta la primera coincidencia) y luego vuelve a traducir cada coincidencia a una nueva línea. esta opción solo funciona si el archivo tiene el siguiente formato
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
Etcétera
sed
comando en la parte inferior es algo retorcido.