2009-11-20 17 views
8

vi desde¿Cómo se usa sed para devolver algo de la primera línea que coincida y salga temprano?

How to use sed to replace only the first occurrence in a file?

Cómo hacer la mayor parte de lo que quiero:

sed -n '0,/.*\(something\).*/s//\1/p' 

Esto encuentra el primer partido de algo y lo extrae (por supuesto, mi ejemplo real es más complicado) . Sé que sed tiene un comando 'quit' que lo hará detenerse temprano, pero no sé cómo combinar la 'q' con la línea anterior para obtener mi comportamiento deseado.

He intentado reemplazar la 'p' con {p; q;} como he visto en algunos ejemplos, pero eso claramente no está funcionando.

+0

¿Puede mostrar más de lo que está recibiendo y lo que quiere y cómo se diferencian? Hice 'echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0, /. * \ (111 \). */S // \ 1/p'' y obtuve uno" 111 ". Entonces hice 'echo -e" aaa 111 aaa \ nbbb 111 bbb "| sed -n '0,/\ (. * \ (111 \). * \)/S // \ 1/p'' para mostrar el línea completa para asegurarse de lo que estaba obteniendo y la salida "aaa 111 aaa" que es lo que esperaba. Tenga en cuenta que no estoy usando 'q'. ¿Cómo "no funciona" para ti? –

+0

Su método genera la salida correcta, pero continúa procesando todo el archivo aunque no haya más trabajo por hacer, lo que es horrible para archivos gigantes o cuando se usa en una canalización.Mi caso de uso específico fue averiguar a través de 'git log' en un árbol importado de git-p4 cuya rama obligatoria se usó para la última confirmación. git log (cuando se llama sin -n registrará cada confirmación que sucedió (cientos de miles para mí). No podemos saber a priori qué valor dar a git por '-n'. Mi solución fue: git log | sed -n '0, /. * \ [git-p4:. * \/\/depot \/blah \/\ ([^ \ /] * \) \ /.*/ s // \ 1/p;/\ [git-p4/q ' – nosatalian

Respuesta

3

Mi caso de uso específico era averiguar a través de 'git log' en un árbol importado git-p4, que forzosamente rama se utilizó para la última confirmación. git log (cuando se llama sin -n registrará cada confirmación que sucedió (cientos de miles para mí)).

No podemos saber a priori qué valor darle a git por '-n'. Después de publicar esto, he encontrado mi solución que era:

git log | sed -n '0,/.*\[git-p4:.*\/\/depot\/blah\/\([^\/]*\)\/.*/s//\1/p; /\[git-p4/ q' 

Todavía me gustaría saber cómo hacer esto con un separador no '/', y sin tener que especificar la parte 'git-P4' dos veces , una vez para la extracción y una para el abandono. Tiene que haber una forma de combinar ambos en la misma línea ...

1

Sed generalmente tiene una opción para especificar más de un patrón para ejecutar (IIRC, es la opción -e). De esta forma, puede especificar un segundo patrón que se cierra después de la primera línea.

Otro enfoque es utilizar sed para extraer la primera línea (sed '1q'), luego de que la tubería a una segunda sed comando (lo que muestran más arriba).

1

uso gawk

gawk '/MATCH/{ 
      print "do something with "$0 
      exit 
}' file 
9

El truco "imprimir y dejar" funciona, si también pones el comando de sustitución en el bloque (en lugar de solo poner la impresión y salir ahí)

Probar:

sed -n '/.*\(something\).*/{s//\1/p;q}' 

Leer esto como: Partido para el patrón dado entre las barras. Si se encuentra este patrón, ejecute las acciones especificadas en el bloque: Reemplazar, imprimir y salir. Normalmente, los patrones de coincidencia y sustitución son iguales, pero esto no es necesario, por lo que el comando 's' también podría contener un RE diferente.

En realidad, esto es bastante similar a lo que ghostdog74 respondió por gawk.

+0

OpenBSD requiere un punto y coma después del comando quit ('q'). –

Cuestiones relacionadas