2011-05-09 10 views
15

quisiera ignorar todas las líneas que se producen antes de un partido en bash (también haciendo caso omiso de la línea encajada. Ejemplo de entrada podría ser¿Cómo ignorar todas las líneas antes de que ocurra una coincidencia en bash?

R1-01.sql 
R1-02.sql 
R1-03.sql 
R1-04.sql 
R2-01.sql 
R2-02.sql 
R2-03.sql 

y si responden a R2-01.sql en esto ya ordenados de entrada me gustaría obtener

R2-02.sql 
R2-03.sql 
+0

¿Puedo sugerir que también Etiqueta esta pregunta con 'sed ¿? Podría hacerlo yo mismo, pero mi edición podría no ser aceptada. Gracias. –

Respuesta

19

muchas maneras posibles. Por ejemplo: si se asume que su entrada está en list.txt

PATTERN="R2-01.sql" 
sed "0,/$PATTERN/d" <list.txt 

porque, alfunciona solo en GNU sed, (p. no funciona en OS X), aquí hay una solución manipulada. ;)

PATTERN="R2-01.sql" 
(echo "dummy-line-to-the-start" ; cat -) < list.txt | sed "1,/$PATTERN/d" 

Esto agregará una línea ficticia de la salida, por lo que el patrón real debe estar en línea el 1 o superior, por lo que el 1,/pattern/ hará obras - Borrado de todo, desde la línea 1 (simulado uno) hasta el patrón.

O puede imprimir líneas según el modelo y eliminar la primera, como:

sed -n '/pattern/,$p' < list.txt | sed '1d' 

con awk, por ejemplo:

awk '/pattern/,0{if (!/pattern/)print}' < list.txt 

o, mi favorito utilizar el siguiente comando perl:

perl -ne 'print unless 1../pattern/' < list.txt 

borra la 1.ª línea cuando el patrón está en 1st l ine ...

otra solución es inversa-delete-revertir

tail -r < list.txt | sed '/pattern/,$d' | tail -r 

si tiene el comando tac usarlo en lugar de tail -r Lo interesant es que el /pattern/,$d' works on the last line but the 1,/patrón/d` doesn' t en el primero.

+0

Estoy usando esto, pero no funciona cuando el partido ocurre en la primera línea. Ver http://stackoverflow.com/questions/17364951/remove-all-lines-before-a-match-with -sed – Fabio

+0

@Fabio sí! la solución correcta es 0,/pattern/Thank you, y agregó una solución que también funciona en sedimentos no GNU. – jm666

+1

La técnica reverse-delete-reverse salvó el día con http://stackoverflow.com/questions/38662085/grep-log4j-for-lines-after-certain-timestamp-in-java – jonayreyes

9

¿Cómo ignorar todas las líneas antes de que ocurra una coincidencia en bash?

El título de la pregunta y su ejemplo no coinciden del todo.

Imprimir todas las líneas de "R2-01.SQL" en sed:

sed -n '/R2-01.sql/,$p' input_file.txt 

Dónde:

  • -n suprime la impresión del espacio de patrones a la salida estándar
  • / empieza y termina el patrón que corresponda (expresión regular)
  • , separa el inicio del rango desde el final
  • $ aborda la última línea en la entrada
  • p se hace eco del espacio de patrones en ese rango a la salida estándar
  • input_file.txt es el archivo de entrada

Imprimir todas las líneas después de "R2-01.sql" en sed:

sed '1,/R2-01.sql/d' input_file.txt 
  • 1 aborda la primera línea de la entrada
  • , separa el inicio del intervalo de desde el extremo
  • / comienza y termina el patrón para que coincida con (expresión regular)
  • $ direcciones de la última línea en la entrada
  • d elimina el espacio de patrones en ese rango de
  • input_file.txt es el archivo de entrada
  • Todo lo que no se eliminó se repite en stdout.
+0

¿Eso imprimirá la línea con el patrón? Parece que el OP no quiere eso. –

+0

@glenn: Depende de qué parte de la pregunta lees. He actualizado mi respuesta. – Johnsyweb

+0

Esto solo funciona con un '' R2-01.sql' 'no codificado ''. – user5359531

2
awk -v pattern=R2-01.sql ' 
    print_it {print} 
    $0 ~ pattern {print_it = 1} 
' 
0

que puede hacer con esto, pero creo que la respuesta de jomo666 era mejor.

sed -nr '/R2-01.sql/,${/R2-01/d;p}' <<END 
    R1-01.sql 
    R1-02.sql 
    R1-03.sql 
    R1-04.sql 
    R2-01.sql 
    R2-02.sql 
    R2-03.sql 
    END 
2

Esto es un poco hacky, pero es fácil de recordar para obtener rápidamente la salida que necesita:

$ grep -A99999 $match $file 

Obviamente se necesita para recoger un valor para -A que es lo suficientemente grande como para que coincida con todos los contenidos; si usa un valor demasiado pequeño, la salida se truncará en silencio.

para asegurarse de obtener todos los de salida que puede hacer:

$ grep -A$(cat $file | wc -l) $match $file 

Por supuesto, en ese momento usted puede ser mejor con las soluciones sed, ya que no se requieren dos lecturas del fichero.

Y si no desea la línea coincidente en sí, simplemente puede canalizar este comando al tail -n+1 al skip the first line of output.

+0

¿Qué sucede si este archivo contiene más de 99999 líneas? Tengo que lidiar con archivos de más de 100000 líneas, por suerte no sigo tus consejos. – SansWord

+0

El segundo ejemplo funcionará para archivos de cualquier tamaño. Como dije, el primero es útil porque es fácil de recordar. Es una alternativa a la solución 'sed', no tienes que hacerlo de esta forma si no quieres. – dimo414

+1

El último comando 'grep' con' wc -l' del archivo es la única solución que he visto publicada que es realmente portátil y flexible. – user5359531

0

Perl es otra opción:

perl -ne 'if ($f){print} elsif (/R2-01\.sql/){$f++}' sql 

acontecerá en la expresión regular como un argumento, utilice -s para permitir que un analizador simple argumento

perl -sne 'if ($f){print} elsif (/$r/){$f++}' -- -r=R2-01\\.sql file 
Cuestiones relacionadas