with special characters another replace syntax sed

special - sed replace word



¿Cómo reemplazar múltiples patrones a la vez con sed? (8)

Aquí hay un awk basado en oogas sed

echo ''abbc'' | awk ''{gsub(/ab/,"xy");gsub(/bc/,"ab");gsub(/xy/,"bc")}1'' bcab

Supongamos que tengo una cadena ''abbc'' y quiero reemplazar:

  • ab -> bc
  • bc -> ab

Si intento dos reemplazos, el resultado no es lo que quiero:

echo ''abbc'' | sed ''s/ab/bc/g;s/bc/ab/g'' abab

Entonces, ¿qué comando sed puedo usar para reemplazar como a continuación?

echo abbc | sed SED_COMMAND bcab

EDITAR : En realidad, el texto podría tener más de 2 patrones y no sé cuántos reemplazos necesitaré. Como había una respuesta que decía que sed es un editor de flujo y sus reemplazos son codiciosos, creo que necesitaré usar un lenguaje de script para eso.


Aquí hay una variación en la respuesta de ooga que funciona para múltiples pares de búsqueda y reemplazo sin tener que verificar cómo se pueden reutilizar los valores:

sed -i '' s//bAB/b/________BC________/g s//bBC/b/________CD________/g s/________//g '' path_to_your_files/*.txt

Aquí hay un ejemplo:

antes de:

some text AB some more text "BC" and more text.

después:

some text BC some more text "CD" and more text.

Tenga en cuenta que /b denota límites de palabras, que es lo que evita que ________ interfiera con la búsqueda (estoy usando GNU sed 4.2.2 en Ubuntu). Si no está utilizando una búsqueda de límites de palabras, entonces esta técnica puede no funcionar.

También tenga en cuenta que esto da los mismos resultados que eliminar s/________//g y agregar && sed -i ''s/________//g'' path_to_your_files/*.txt al final del comando, pero no requiere especificar el camino dos veces.

Una variación general de esto sería usar /x0 o _/x0_ en lugar de ________ si sabe que no aparecen valores nulos en sus archivos, como sugirió jthill .


Esto podría funcionar para usted (GNU sed):

sed -r ''1{x;s/^/:abbc:bcab/;x};G;s/^//n/;:a;//n/n/{P;d};s//n(ab|bc)(.*/n.*:(/1)([^:]*))//4/n/2/;ta;s//n(.)//1/n/;ta'' file

Esto utiliza una tabla de búsqueda que se prepara y se mantiene en el espacio de espera (HS) y luego se agrega a cada línea. Un marcador único (en este caso /n ) se antepone al comienzo de la línea y se utiliza como un método para avanzar en la búsqueda a lo largo de la línea. Una vez que el marcador llega al final de la línea, el proceso finaliza y se imprime la tabla de búsqueda y los marcadores que se descartan.

NB La tabla de búsqueda se prepara desde el principio y se elige un segundo marcador único (en este caso:) para no chocar con las cadenas de sustitución.

Con algunos comentarios:

sed -r '' # initialize hold with :abbc:bcab 1 { x s/^/:abbc:bcab/ x } G # append hold to patt (after a /n) s/^//n/ # prepend a /n :a //n/n/ { P # print patt up to first /n d # delete patt & start next cycle } s//n(ab|bc)(.*/n.*:(/1)([^:]*))//4/n/2/ ta # goto a if sub occurred s//n(.)//1/n/ # move one char past the first /n ta # goto a if sub occurred ''

La tabla funciona así:

** ** replacement :abbc:bcab ** ** pattern


Puede ser un enfoque más simple para la ocurrencia de un solo patrón que puede probar a continuación: echo ''abbc'' | sed ''s / ab / bc /; s / bc / ab / 2''

Mi salida:

~# echo ''abbc'' | sed ''s/ab/bc/;s/bc/ab/2'' bcab

Para múltiples ocurrencias de patrón:

sed ''s//(ab/)/(bc/)//2/1/g''

Ejemplo

~# cat try.txt abbc abbc abbc bcab abbc bcab abbc abbc bcab ~# sed ''s//(ab/)/(bc/)//2/1/g'' try.txt bcab bcab bcab bcab bcab bcab bcab bcab bcab

Espero que esto ayude !!


Siempre uso múltiples declaraciones con "-e"

$ sed -e ''s:AND:/n&:g'' -e ''s:GROUP BY:/n&:g'' -e ''s:UNION:/n&:g'' -e ''s:FROM:/n&:g'' file > readable.sql

Esto agregará un ''/ n'' antes de todos los AND, GROUP BY, UNION y FROM, mientras que ''&'' significa la cadena coincidente y ''/ n &'' significa que desea reemplazar la cadena coincidente con un ''/ n'' antes del ''coincidente ''


Tal vez algo como esto:

sed ''s/ab/~~/g; s/bc/ab/g; s/~~/bc/g''

Reemplace ~ con un carácter que sabe que no estará en la cadena.


Tcl tiene un builtin para esto

$ tclsh % string map {ab bc bc ab} abbc bcab

Esto funciona caminando la cadena de un personaje a la vez haciendo comparaciones de cadenas comenzando en la posición actual.

En perl:

perl -E '' sub string_map { my ($str, %map) = @_; my $i = 0; while ($i < length $str) { KEYS: for my $key (keys %map) { if (substr($str, $i, length $key) eq $key) { substr($str, $i, length $key) = $map{$key}; $i += length($map{$key}) - 1; last KEYS; } } $i++; } return $str; } say string_map("abbc", "ab"=>"bc", "bc"=>"ab"); ''

bcab


sed es un editor de flujo. Busca y reemplaza con avidez. La única forma de hacer lo que solicitó es usar un patrón de sustitución intermedio y volver a cambiarlo al final.

echo ''abcd'' | sed -e ''s/ab/xy/;s/cd/ab/;s/xy/cd/''