¿Cómo se pasa una variable que contiene barras como un patrón de sed?

Por ejemplo, si tengo la siguiente variable:

var="/Users/Documents/name/file"

Quiero pasar a sed así como:

sed "s/$var/replace/g" "$file"

Sin embargo obtengo errores. ¿Cómo puedo eludir el problema?

InformationsquelleAutor Bolboa | 2015-01-05

6 Comentarios

  1. 140

    Uso alternativo de los regex delimitador como sed permite el uso de cualquier delimitador (incluyendo los caracteres de control):

    sed "s~$var~replace~g" $file
    • No funciona. Trato de sed-i «s~bla~$var~g» archivo » y obtener: «sed-e de expresión #1, char 70: sin `s’ comando». Me han confirmado que el culpable es una barra en $var. Variantes de esta solución a esto son por todo el lugar y ninguna de ellas funciona. Era sed actualizado recientemente? Estoy en la v4.2.2 en Ubuntu 14.04.4 LTS.
    • Eso depende de qué es el valor de $var
    • No funciona con ~ como @PaulEricson observado, pero todavía funciona con |
    • en ubuntu 16.04 funciona con ~
    • no trabajo para mí. Puedo obtener sed: -e expression #1, char 17: unknown option to `s' (stackoverflow.com/a/27788661/860878 trabajado)
    • La última «~» (después de g), no parece ser necesaria, al menos para AWS de Amazon Linux (CentOS)basado en el
    • Gracias, que era una errata, fijo ahora.

  2. 38

    Un puro bash respuesta: el uso de parámetro de expansión a de barra diagonal inversa escapar de la barras de la variable:

    var="/Users/Documents/name/file"
    sed "s/${var//\//\/}/replace/g" $file
    • Esta es una buena manera, porque no siempre se sabe qué caracteres que contiene la variable. Lo que siempre se puede escapar de la sed delimitador si hay una duda.Por ejemplo : sed «s:${var//:/\\:}:reemplazar:g» $archivo
    • Hermoso. Hizo el cambio de nombre de algunos scripts de mina mucho más limpio.
    • Que me ha ayudado mucho gracias 🙂
    • Aprendido algo hermoso el día de hoy, gracias. Debe ser aceptado respuesta.
    • Algo más de claridad en el modelo se utiliza aquí: ${parameter/pattern/string}. Así, en este caso, el parámetro es var, el patrón es /\/, y la cadena es \\/. Todas las instancias del patrón son reemplazados debido a que el patrón comienza con una /.
    • y así, el slash de que el patrón no es realmente parte de la trama a reemplazar.
    • es verdad, aunque en la documentación de referencia que dicen «Si el patrón comienza con ‘/’, todos los partidos de patrón son reemplazados con una cuerda.» Yo estaba siguiendo la convención de hablar de ella como parte del patrón. Parece una torpe manera de hablar de ello, pero aunque la sintaxis es bastante torpe para empezar en mi opinión.

  3. 26

    Otra forma de hacerlo, aunque más feo que anubhava la respuesta, es por escapar de todas las barras en la var utilizando otro sed comando:

    var=$(echo "$var" | sed 's/\//\\//g')

    entonces, esto va a funcionar:

    sed "s/$var/replace/g" $file
  4. 10

    Utilizando / en el sed como un delimitador se entra en conflicto con las barras de la variable cuando se sustituye y como resultado, se obtendrá un error. Una manera de evitar esto es utilizar otro delimitador de que es única de los caracteres que se encuentra en esa variable.

    var="/Users/Documents/name/file"

    puede utilizar el octotborpe personaje que se adapte a la ocasión (o de cualquier otro carácter que no es un / para facilidad de uso)

    sed "s#$var#replace#g" 

    o

    sed 's#$'$var'#replace#g'

    esto es adecuado cuando la variable no contiene espacios

    o

    sed 's#$"'$var'"#replace#g'

    Es mejor utilizar el de arriba, ya que estamos interesados en la sustitución de lo que es en la que la variable sólo como comparación con doble citando el conjunto de comandos que puede causar que su shell para interpet cualquier carácter que podría ser considerado como una concha especial carácter a la shell.

    • No funciona. Trato de sed-i «s~bla~$var~g» archivo » y obtener: «sed-e de expresión #1, char 70: sin `s’ comando». Me han confirmado que el culpable es una barra en $var. Variantes de esta solución a esto son por todo el lugar y ninguna de ellas funciona. Era sed actualizado recientemente? Estoy en la v4.2.2 en Ubuntu 14.04.4 LTS.
    • Soy incapaz de reproducir esto en cualquier Ubuntu disponible para mí. Si su $var contiene ~, obviamente necesitarás escoger un delimitador distinto. El «sin error» suena como su $var contiene un salto de línea; usted podría ser capaz de solucionarlo por una barra inversa, escapa cada salto de línea en el valor, pero no creo que esto es totalmente portátil. Este es, en general, no relacionados con el problema de las barras en el valor.
    • Ah, y su cotización es incorrecta, usted no debe tener el nombre del archivo dentro de las comillas. sed -i "s~blah~$var~g" file con comillas sólo alrededor del sed secuencia de comandos.
  5. 5

    Esta es una vieja pregunta, pero ninguna de las respuestas aquí discutir otras operaciones distintas de la s/from/to/ en mucho detalle.

    La forma general de una sed declaración es

    *address* *action*

    donde dirección puede ser una expresión regular o un número de línea de la gama (o vacío, en cuyo caso el acción se aplica a cada línea de entrada). Así, por ejemplo

    sed '1,4d' file

    va a eliminar las líneas 1 a la 4 (la dirección es el número de la línea de gama 1,4 y la acción es el d comando delete); y

    sed '/ick/,$s/foo/bar/' file

    reemplazará a la primera aparición de foo con bar en cualquier línea entre el primer partido en el regex ick y al final del archivo (el dirección es el rango /ick/,$ y la acción es el s comando sustituir s/foo/bar/).

    En este contexto, si ick vino de una variable, se podría hacer

    sed "/$variable/,$s/foo/bar/"

    (observe el uso de comillas dobles en lugar de una sola, por lo que la consola puede interpolar la variable, y la necesidad de cita literal signo de dólar dentro de comillas dobles) pero si la variable contiene una barra, obtendrá un error de sintaxis. (El shell expande la variable, luego pasa a la cadena resultante a sed; así sed sólo se ve el texto literal – no tiene ningún concepto de el shell de variables).

    La cura es el uso de diferentes delimitador (donde obviamente se necesita para ser capaz de utilizar un personaje que no puede producirse en el valor de la variable), pero a diferencia de los s%foo%bar% caso, también se necesita una barra invertida antes de que el delimitador si desea utilizar un delimitador distinto que el valor predeterminado /:

    sed "\%$variable%,$s/foo/bar/" file

    (dentro de comillas simples, de una sola barra diagonal inversa, obviamente, sería suficiente), o por separado escapar de cada barra en el valor. Este particular sintaxis de Bash solo:

    sed "/${variable//\//\/}/,$s/foo/bar/" file

    o si utiliza un shell diferente, intente

    escaped=$(echo "$variable" | sed 's%/%\/%g')
    sed "s/$escaped/,$s/foo/bar/" file

    Para mayor claridad, si $variable contenidos de la cadena 1/2, a continuación, los comandos de arriba sería el equivalente a

    sed '\%1/2%,$s/foo/bar/' file

    en el primer caso, y

    sed '/1\/2/,$s/foo/bar/' file

    en el segundo.

  6. 2

    Uso de Perl, donde las variables son ciudadanos de primera clase, no sólo la expansión de macros:

    var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
    • -p lee la línea de entrada de línea e imprime la línea después del procesamiento
    • \Q cita a todos los metacaracteres en la siguiente cadena (no se necesita para el valor que aquí se presenta, pero es necesario si el valor contenido [ o algunos otros valores especiales para regular expresisons)
    • La única utilidad general de respuesta a decenas de «utilización de variables en el sed expresión» preguntas a través de Intercambio de la Pila. Todo lo demás es, efectivamente, «escapar de algo que es especial para la sed», que es prácticamente inútil dada la variabilidad de las variables y de sed.

Dejar respuesta

Please enter your comment!
Please enter your name here