En mi script bash tengo una cadena externa (recibida del usuario), que debería usar en el patrón sed.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
¿Cómo puedo escapar de la $REPLACE
cadena para que sea aceptada de forma segura sed
como un reemplazo literal?
NOTA: El KEYWORD
es una subcadena mudo de coincidencias, etc. No es suministrada por el usuario.
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Respuestas:
Advertencia : Esto no considera nuevas líneas. Para una respuesta más profunda, vea esta pregunta SO en su lugar. (Gracias, Ed Morton y Niklas Peter)
Tenga en cuenta que escapar de todo es una mala idea. Sed necesita escapar de muchos personajes para obtener su significado especial. Por ejemplo, si escapa un dígito en la cadena de reemplazo, se convertirá en una referencia inversa.
Como dijo Ben Blank, solo hay tres caracteres que deben escaparse en la cadena de reemplazo (se escapa, barra diagonal para el final de la declaración y & para reemplazar todos):
Si alguna vez necesita escapar de la
KEYWORD
cadena, la siguiente es la que necesita:Y puede ser utilizado por:
Recuerde, si usa un carácter que no sea
/
delimitador, debe reemplazar la barra diagonal en las expresiones anteriores con el carácter que está usando. Vea el comentario de PeterJCLaw para una explicación.Editado: debido a algunos casos de esquina que anteriormente no se tenían en cuenta, los comandos anteriores han cambiado varias veces. Verifique el historial de edición para más detalles.
fuente
KEYWORD
, en GNU sed , aquí hay 2 caracteres más^
,$
no mencionados anteriormente:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
en bash. Las comillas dobles se tratan como el 'foo' y 'bar' a su alrededor.El comando sed le permite usar otros caracteres en lugar de
/
como separador:Las comillas dobles no son un problema.
fuente
.
que de lo contrario tiene un significado especial. Edité tu respuesta.sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
consed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
y eso no hace lo mismo.s
comando (como sustituto) de sed le permite usar otros caracteres en lugar de / como separador. Además, esta sería una respuesta a cómo usar sed en URL con caracteres de barra diagonal. No responde a la pregunta de OP cómo escapar de una cadena ingresada por un usuario, que podría contener /, \, pero también # si decide usar eso. Y además, URI puede contener # tambiénLos únicos tres caracteres literales que se tratan especialmente en la cláusula de reemplazo son
/
(para cerrar la cláusula),\
(para escapar de caracteres, referencia, etc.) y&
(para incluir la coincidencia en el reemplazo). Por lo tanto, todo lo que necesitas hacer es escapar de esos tres personajes:Ejemplo:
fuente
Basado en las expresiones regulares de Pianosaurus, hice una función bash que escapa tanto a la palabra clave como al reemplazo.
Así es como lo usa:
fuente
man echo
), haciendo que la tubería se comporte inesperadamente cuando su argumento$1
comienza con un guión. En cambio, puede comenzar su tubería conprintf '%s\n' "$1"
.Es un poco tarde para responder ... pero hay una manera mucho más simple de hacer esto. Simplemente cambie el delimitador (es decir, el carácter que separa los campos). Entonces, en lugar de
s/foo/bar/
escribirs|bar|foo
.Y, aquí está la manera fácil de hacer esto:
El resultado resultante carece de esa desagradable cláusula DEFINER.
fuente
&
y `` aún se debe escapar, al igual que el delimitador, lo que se elija.$
en la cadena a punto de cambiar, y mantener el significado de$
en la cadena de reemplazo. Digamos que quiero cambiar$XXX
el valor de variable$YYY
,sed -i "s|\$XXX|$YYY|g" file
funciona bien.Resulta que estás haciendo la pregunta equivocada. También hice la pregunta equivocada. La razón por la que está mal es el comienzo de la primera oración: "En mi script bash ...".
Tuve la misma pregunta y cometí el mismo error. Si usa bash, no necesita usar sed para hacer reemplazos de cadenas (y es mucho más limpio usar la función de reemplazo incorporada en bash).
En lugar de algo como, por ejemplo:
puedes usar las funciones de bash exclusivamente:
fuente
$A
y$B
no están entre comillas, pero no lo son. Las comillas dentro de la${}
no coinciden con las comillas fuera de ella.var='has space'
):OUTPUT=${INPUT//"$A"/"$B"}
es seguro.Use awk, es más limpio:
fuente
awk
es que no tiene nada similarsed -i
, lo que resulta extremadamente útil el 99% del tiempo.Aquí hay un ejemplo de un AWK que usé hace un tiempo. Es un AWK que imprime nuevos AWKS. AWK y SED son similares, puede ser una buena plantilla.
Parece excesivo, pero de alguna manera esa combinación de citas funciona para mantener el 'impreso como literales. Entonces, si recuerdo correctamente, las variables están rodeadas de comillas como esta: "$ 1". Pruébalo, avísame cómo funciona con SED.
fuente
Tengo una mejora sobre la función sedentaria, que romperá con caracteres especiales como tabulación.
Entonces, ¿qué es diferente?
$1
y$2
entre comillas para evitar expansiones de shell y preservar pestañas o espacios dobles.Tubería adicional
| sed -e 's:\t:\\t:g'
(me gusta:
como token) que transforma una pestaña en\t
.fuente
Estos son los códigos de escape que he encontrado:
fuente
no olvides todo el placer que se produce con la limitación de shell "y"
entonces (en ksh)
fuente
Si solo está buscando reemplazar el valor de la Variable en el comando sed, simplemente elimine el Ejemplo:
fuente
Si el caso es que está generando una contraseña aleatoria para pasar para
sed
reemplazar el patrón, entonces elige tener cuidado con qué conjunto de caracteres en la cadena aleatoria. Si elige una contraseña creada al codificar un valor como base64, entonces solo hay un carácter que es posible en base64 y también es un carácter especial en elsed
patrón de reemplazo. Ese carácter es "/", y se elimina fácilmente de la contraseña que está generando:fuente
Una manera más fácil de hacer esto es simplemente construir la cadena de antemano y usarla como parámetro para
sed
fuente
REPLACE=/
dased: -e expression #1, char 12: unknown option to `s'