Respuestas:
Use un delimitador de expresiones regulares alternativo, ya sed
que le permite usar cualquier delimitador ( incluidos los caracteres de control ):
sed "s~$var~replace~g" $file
$var
Una respuesta pura de bash: use la expansión de parámetros para la barra invertida y escape de cualquier barra en la variable:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}
. Entonces, en este caso, el parámetro es var
, el patrón es /\/
y la cadena es \\/
. Todas las instancias del patrón se reemplazan porque el patrón comienza con a /
.
El uso de /
in sed como delimitador entrará en conflicto con las barras en la variable cuando se sustituya y, como resultado, obtendrá un error. Una forma de eludir esto es usar otro delimitador que sea exclusivo de cualquier carácter que esté en esa variable.
var="/Users/Documents/name/file"
puede utilizar el carácter octothorpe que se adapte a la ocasión (o cualquier otro carácter que no sea /
para facilitar su 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 más prudente usar lo anterior, ya que estamos interesados en sustituir lo que sea que esté en esa variable solo en comparación con las comillas dobles del comando completo, lo que puede hacer que su shell interpele cualquier carácter que pueda considerarse un carácter especial de shell en el shell.
$var
contiene ~
, obviamente deberá elegir un delimitador diferente. El error "no terminado" parece que tu $var
contiene una nueva línea; es posible que pueda solucionarlo haciendo una barra invertida escapando de cada nueva línea en el valor, pero no creo que esto sea completamente portátil. En general, esto no está relacionado con el problema de las barras en el valor.
sed -i "s~blah~$var~g" file
con comillas solo alrededor del sed
guión real .
Esta es una pregunta antigua, pero ninguna de las respuestas aquí discute las operaciones más que s/from/to/
con mucho detalle.
La forma general de una sed
declaración es
*address* *action*
donde la dirección puede ser un rango de expresiones regulares o un rango de número de línea (o vacío, en cuyo caso la acción se aplica a cada línea de entrada). Así por ejemplo
sed '1,4d' file
eliminará las líneas 1 a 4 (la dirección es el rango del número de línea 1,4
y la acción es el d
comando de eliminación); y
sed '/ick/,$s/foo/bar/' file
reemplazará la primera aparición de foo
con bar
en cualquier línea entre la primera coincidencia en la expresión regular ick
y el final del archivo (la dirección es el rango /ick/,$
y la acción es el s
comando de sustitución s/foo/bar/
).
En este contexto, si ick
proviene de una variable, podría hacer
sed "/$variable/,\$s/foo/bar/"
(observe el uso de comillas dobles en lugar de simples, de modo que el shell pueda interpolar la variable, y la necesidad de citar el signo de dólar literal entre comillas dobles) pero si la variable contiene una barra, obtendrá un error de sintaxis. (El shell expande la variable, luego pasa la cadena resultante a sed
; por lo tanto, sed
solo ve texto literal, no tiene el concepto de las variables del shell).
La cura es usar un delimitador diferente (donde obviamente necesita poder usar un carácter que no puede ocurrir en el valor de la variable), pero a diferencia del s%foo%bar%
caso, también necesita una barra invertida antes del delimitador si desea usar un carácter diferente delimitador que el predeterminado /
:
sed "\\%$variable%,\$s/foo/bar/" file
(entre comillas simples, una barra invertida obviamente sería suficiente); o puede escapar por separado de cada barra en el valor. Esta sintaxis en particular es solo Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
o si usa un caparazón diferente, intente
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Para mayor claridad, si $variable
contiene la cadena 1/2
, los comandos anteriores serían equivalentes a
sed '\%1/2%,$s/foo/bar/' file
en el primer caso, y
sed '/1\/2/,$s/foo/bar/' file
en el segundo.
Utilice Perl, donde las variables son ciudadanos de primera clase, no solo macros en expansión:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
lee la entrada línea por línea e imprime la línea después del procesamiento\Q
cita todos los metacaracteres en la siguiente cadena (no es necesario para el valor presentado aquí, pero es necesario si el valor contiene [
o algunos otros valores especiales para expresiones regulares)