sed: elimina todas las apariciones de una cadena excepto la primera

14

Tengo un archivo de registro con marcas de tiempo. Ocasionalmente, hay varias marcas de tiempo en una línea. Ahora me gustaría eliminar todas las marcas de tiempo de una línea, pero conservar la primera.

Puedo hacerlo, s/pattern//2pero eso solo elimina la segunda ocurrencia y sedno permite algo así s/pattern//2-.

¿Alguna sugerencia?

Folkert van Heusden
fuente
Debería haber dicho que es el sed de busybox. Lo siento por eso.
Folkert van Heusden

Respuestas:

4

Con GNU sed:

sed 's/pattern//2g'

El 2especifica que el segundo patrón y todo el resto gdeben eliminarse. Entonces esto mantendrá el primero.

αғsнιη
fuente
1
Qué Cygwin tiene (un puerto de, aparentemente) y MacOS no. Achh! Esta solución es mucho más elegante.
r_alex_hall
7

Esto debería funcionar (reemplace _ por algo más si choca con sus registros):

sed -e 's/pattern/_&/1' -e 's/\([^_]\)pattern//g' -e 's/_\(pattern\)/\1/'
jlliagre
fuente
1
si alguna vez quieres un delimitador único, úsalo \n.
mikeserv
5
sed -e ':begin;s/pattern//2;t begin'

o sin el sed goto:

sed -e 's/\(pattern\)/\1\n/;h;s/.*\n//;s/pattern//g;H;g;s/\n.*\n//'

Las soluciones genéricas para eliminar de la enésima posición (3 por ejemplo) son:

sed -e ':begin;s/pattern//4;t begin'
sed -e 's/\(pattern\)/\1\n/;h;s/.*\n//3;s/pattern//g;H;g;s/\n.*\n//'
jfg956
fuente
1

Una ligera variación en la respuesta de @ jillagre (modificada para robustez) podría verse así:

sed 's/p\(attern\)/p\n\1/;s///g;s/\n//'

... pero en algunos seds puede que necesite reemplazar el nen el lado derecho de la primera s///declaración de sustitución con un carácter literal de línea de \nhilo.

mikeserv
fuente