Supongamos que tengo ‘abbc’ cadena y quiero reemplazar:

  • ab -> bc
  • bc -> ab

Si yo lo intente dos reemplaza 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 el de abajo?

echo abbc | sed SED_COMMAND
bcab

EDITAR:
En realidad, el texto puede tener más de 2 patrones y no sé cuántas reemplaza voy a necesitar. Ya hubo una respuesta diciendo que sed es un editor de flujo y su reemplaza son ávidamente creo que será necesario utilizar algún lenguaje de script para eso.

  • Qué necesitas para hacer reemplazos múltiples en la misma línea? Si no sólo la caída de la g bandera de ambas s/// comandos y que va a funcionar.
  • Sí, la misma línea.
  • Te perdiste el punto de mi pregunta. Me refería a hacer que usted necesita hacer que cada uno de reemplazo más de una vez en la misma línea. Hay más de una coincidencia para ab o bc en la entrada original.
  • Lo siento @EtanReisner he entendido mal, La respuesta es sí. el texto puede tener varias sustituciones.
InformationsquelleAutor DaniloNC | 2014-10-26

8 Comentarios

  1. 272

    Tal vez algo como esto:

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

    Reemplazar ~ con un personaje que sabe no estar en la cadena.

    • GNU sed maneja nuls, así que usted puede utilizar \x0 para ~~.
    • Es g necesario y qué hace?
    • es global – reemplaza todas las instancias del patrón en cada línea, en lugar de sólo la primera (que es el comportamiento por defecto).
    • Por favor vea mi respuesta stackoverflow.com/a/41273117/539149, para una variación de ooga la respuesta de que puede sustituir a las múltiples combinaciones de forma simultánea.
    • que usted sabe que no estará en la cadena de Para el código de producción, no nunca hace ninguna suposición acerca de la entrada. Para las pruebas, así, las pruebas nunca realmente demostrar la corrección, pero una buena idea para una prueba es: Usar el mismo script como entrada.
  2. 15

    Yo siempre uso las 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

    Se agregará un ‘\n’ antes de todo Y, de GRUPO, de UNIÓN y DE s, mientras que la ‘&’ significa que la cadena coincidente y ‘\n&’ significa desea reemplazar la cadena coincidente con un ‘\n’ antes de la ‘coincidente’

    • Esto no funciona en macos sed.
  3. 10

    Aquí es una variación sobre ooga la respuesta que funciona para varias buscar y reemplazar pares sin tener que comprobar cómo los valores pueden ser reutilizados:

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

    Aquí está un ejemplo:

    antes:

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

    después:

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

    Nota que \b indica los límites de la palabra, que es lo que impide la ________ de interferir con la búsqueda (estoy usando GNU sed 4.2.2 en Ubuntu). Si usted no está utilizando un límite de palabras de búsqueda, a continuación, esta técnica puede no funcionar.

    También tenga en cuenta que este da los mismos resultados que la eliminación de la s/________//g y anexando && sed -i 's/________//g' path_to_your_files/*.txt al final del comando, pero no es necesario especificar la ruta de acceso dos veces.

    Una variación general de esto sería el uso de \x0 o _\x0_ en lugar de ________ si sabe que no hay valores nulos aparecen en sus archivos, como jthill sugerido.

    • Estoy de acuerdo con hagello del comentario anterior acerca de no hacer suposiciones de lo que la entrada puede contener. Por lo tanto, yo, personalmente, siento que esta es la solución más confiable, a un lado de la tubería sed en la parte superior de uno al otro (sed 's/ab/xy/' | sed 's/cd/ab/' .....)
  4. 7

    sed es un editor de flujo. Busca y reemplaza con avidez. La única manera de hacer lo que usted pidió es el uso de un intermedio de sustitución de patrón y cambiando de nuevo en la final.

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

  5. 4

    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.*:()([^:]*))/\n/;ta;s/\n(.)/\n/;ta' file
    

    Este utiliza una tabla de búsqueda que está preparado y que se celebró en la bodega del espacio (HS) y, a continuación, se anexa a cada línea. Un marcador único (en este caso \n) se antepone al inicio de la línea y se utiliza como un método a golpe-a lo largo de la búsqueda en toda la longitud de la línea. Una vez que el marcador llegue al final de la línea se ha terminado el proceso y se imprime la tabla de búsqueda y marcadores de ser desechado.

    N. B. La tabla de búsqueda es preparado al inicio y un segundo marcador único (en este caso :) elige de manera que no choque 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.*:()([^:]*))/\n/
      ta       # goto a if sub occurred
    
      s/\n(.)/\n/ # move one char past the first \n
      ta       # goto a if sub occurred
    '
    

    La tabla funciona de la siguiente manera:

       **   **   replacement
    :abbc:bcab
     **   **     pattern
    
  6. 2

    Tcl tiene un builtin para este

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

    Esto funciona por caminar la cuerda de un personaje en un tiempo haciendo las comparaciones de cadenas de partida 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
    
  7. 1

    Puede ser un enfoque más sencillo para un solo patrón de ocurrencia usted puede tratar como 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 varias apariciones de patrón:

    sed 's/\(ab\)\(bc\)//g'
    

    Ejemplo

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

    Espero que esto ayude !!

  8. 0

    Aquí es un awk basado en oogas sed

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

Dejar respuesta

Please enter your comment!
Please enter your name here