Sed: ¿Reemplazar el patrón en cada segunda línea nueva?

10

¿Hay alguna manera de decir sedque reemplace el patrón en cada segundo caso? ¿O al menos en cada segunda línea? (Claro que es posible con un script, pero me preguntaba si sedpuedo hacerlo).

Editar

encontré

sed -e "s/pattern/replacement/g;n"

Pero reemplazó cada primera ocurrencia, no la segunda.

Ejemplo

Fichero de entrada:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Salida deseada:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement
Matthieu Riegler
fuente

Respuestas:

6

ver /programming/5858200/sed-replace-every-nth-occurrence

La solución usa awk en lugar de sed, pero "usa la herramienta adecuada para el trabajo". Puede o no ser posible hacerlo en sed pero, incluso si lo es, será mucho más fácil en una herramienta como awk o perl.

cas
fuente
1
Usando lo que aprendí allí, sirvienta sed -e 'n;s/2004-2009/6e législature/g'que resolvió mi problema.
Matthieu Riegler
1
que no se producirá cada segundo , buscará su patrón en cada segunda línea . es decir, omita las líneas 1ra, 3ra, 5ta, 7ma, etc. por supuesto, eso podría funcionar para su documento en particular.
cas
Sí lo sé. eso es lo que realmente necesitaba.
Matthieu Riegler
14
sed 's/pattern/replacement/2'

Reemplazará la segunda aparición en cada línea que tenga el patrón.


si tienes GNU sed:

sed '1~2N ; s/pattern/replacement/2'

Comenzando desde la línea uno 1, la línea después de que se agregará al espacio del patrón N, el scomando reemplazará la segunda aparición del patrón. luego sedmoverá dos líneas hacia abajo ~2y repetirá.

llua
fuente
No quiero el segundo sino cada segundo.
Matthieu Riegler
Tengo un patrón por línea. Eso no funcionará.
Matthieu Riegler
Hubiera sido bueno saber eso antes. ¿Entonces el patrón ocurre en la línea uno, dos, tres y cuatro (etc.), y desea reemplazar el patrón en la línea dos, cuatro, etc.?
llua
una alternativa más corta puede ser code(sed '1 ~ 2s / patrón / reemplazo /')
jaap
2

La interpretación simple:

En la primera línea que contiene al menos una aparición de PATTERN, desea ignorarlo e imprimir la línea tal como está. En la segunda línea que contiene al menos una aparición de PATTERN, desea reemplazar la primera instancia de PATTERN con REPLACEMENT. En la tercera línea que contiene al menos una aparición de PATTERN, desea imprimir la línea tal como está. En la cuarta línea que contiene al menos una aparición de PATTERN, desea reemplazar la primera instancia de PATTERN con REPLACEMENT. Y así. Las líneas que no coinciden con PATTERN deben imprimirse sin cambios.

Esto se puede hacer fácilmente con Sed así:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

O, con menos espacios en blanco y una etiqueta más corta:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

EDITAR: Acabo de releer la pregunta y vi la interpretación más difícil:

Reemplace la segunda aparición de PATTERN en todo el documento con REPLACEMENT, ya sea que ocurra en la misma línea que la primera aparición o no. Deje las primeras y terceras ocurrencias sin alteraciones. Etc.

Creo que esto también se puede hacer con Sed, aunque es MUCHO más complicado y creo que depende de la expresión regular que se use. Intentaré resolver algo y publicarlo, pero dejaré que esta respuesta se mantenga con la versión simple anterior por ahora.

Comodín
fuente
reemplace su test con un quit y tome información como, { sed '...'; cat; } <inputpara un solo reemplazo
mikeserv
1

Estabas muy cerca, solo salta la primera línea:

sed '1n;s/pattern/replacement/;n'

¿Por qué debería awkser la mejor herramienta en este caso?

Philippos
fuente
0

Un patrón de símbolo dentro de una línea: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Cada segundo patrón (solo puede aparecer una coincidencia de patrón por línea. Si aparecen dos o más coincidencias por línea, solo se reemplazará la segunda)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
prisa
fuente