Tome el siguiente script:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Si intento ejecutar esto en sh
( dash
aquí), fallará debido a los paréntesis, que deben escaparse. Pero no necesito escapar de las barras diagonales (entre los octetos, o en el \s
o \1
). ¿Cuál es la regla aquí? ¿Qué pasa cuando necesito usar {...}
o [...]
? ¿Hay una lista de lo que hago y no necesito escapar?
shell-script
sed
quoting
desviarse
fuente
fuente
function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed
Respuestas:
Aquí hay dos niveles de interpretación: el caparazón y sed.
En el shell, todo entre comillas simples se interpreta literalmente, excepto las comillas simples. Puede escribir una cita simple entre comillas simples
'\''
(comilla simple cerrada, una comilla simple literal, comilla simple abierta).Sed usa expresiones regulares básicas . En un BRE, para que sean tratados literalmente, los caracteres
$.*[\^
deben ser citados precediéndolos con una barra diagonal inversa, excepto dentro de los conjuntos de caracteres ([…]
). Las letras, los dígitos y(){}+?|
no se deben citar (puede salirse con la cita de algunos de estos en algunas implementaciones). Las secuencias\(
,\)
,\n
, y, en algunas implementaciones\{
,\}
,\+
,\?
,\|
y otra barra invertida + alfanuméricos tienen significados especiales. Puede salirse con la suya sin cotizar$^
en algunas posiciones en algunas implementaciones.Además, necesita una barra invertida antes
/
si va a aparecer en la expresión regular fuera de las expresiones de paréntesis. Puede elegir un carácter alternativo como delimitador escribiendo, por ejemplo,s~/dir~/replacement~
o\~/dir~p
; necesitará una barra invertida antes del delimitador si desea incluirlo en el BRE. Si elige un personaje que tiene un significado especial en un BRE y desea incluirlo literalmente, necesitará tres barras invertidas; No recomiendo esto, ya que puede comportarse de manera diferente en algunas implementaciones.En pocas palabras, para
sed 's/…/…/'
:'\''
para terminar con una comilla simple en la expresión regular.$.*/[\]^
y solo esos caracteres (pero no dentro de las expresiones entre corchetes). (Técnicamente, no deberías poner una barra invertida antes,]
pero no conozco una implementación que trate]
y de manera\]
diferente fuera de las expresiones de paréntesis).-
que se trate literalmente, asegúrese de que sea el primero o el último ([abc-]
o[-abc]
no).[a-bc]
^
que se trate literalmente, asegúrese de que no sea primero (use[abc^]
, not).[^abc]
]
en la lista de caracteres que coinciden con una expresión de paréntesis, conviértalo en el primer carácter (o el primero después^
de un conjunto negado):[]abc]
o[^]abc]
(no).[abc]]
ni[abc\]]
En el texto de reemplazo:
&
y\
deben ser citados precediéndolos con una barra diagonal inversa, al igual que el delimitador (generalmente/
) y las nuevas líneas.\
seguido de un dígito tiene un significado especial.\
seguido de una letra tiene un significado especial (caracteres especiales) en algunas implementaciones, y\
seguido de algún otro medio de caracteres\c
oc
dependiendo de la implementación.sed 's/…/…/'
), use'\''
para poner una comilla simple en el texto de reemplazo.Si la expresión regular o el texto de reemplazo proviene de una variable de shell, recuerde que
\n
(que nunca coincidirá a menos que tenga otrosed
código que agregue caracteres de nueva línea al espacio del patrón). Pero tenga en cuenta que no funcionará dentro de las expresiones de paréntesis con algunassed
implementaciones.&
,\
y saltos de línea deben ser citado.sed -e "s/$BRE/$REPL/"
.fuente
\\*
). Ejemplo:echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
El problema que está experimentando no se debe a la interpolación y los escapes de shell, sino a que está intentando utilizar la sintaxis de expresión regular extendida sin pasar la opción
-r
o--regexp-extended
.Cambia tu línea sed de
a
y funcionará como creo que pretendes.
De manera predeterminada, sed uses utiliza expresiones regulares básicas (piense en el estilo grep), lo que requeriría la siguiente sintaxis:
fuente
-r
como opción era lo que era necesario en mi caso.A menos que desee interpolar una variable de shell en la expresión sed, use comillas simples para toda la expresión porque hacen que todo entre ellas se interprete como está, incluidas las barras diagonales inversas.
Por lo tanto, si desea ver,
s/\(127\.0\.1\.1\)\s/\1/
coloque comillas simples alrededor y el shell no tocará los paréntesis o las barras invertidas. Si necesita interpolar una variable de shell, ponga solo esa parte entre comillas dobles. P.ejEsto le ahorrará la molestia de recordar qué metacaracteres de shell no se escapan con comillas dobles.
fuente
sed
vers/(127\.0\.1\.1)/...
, pero poner eso en un script de shell como está no funciona. Lo que estás diciendo acerca de que el caparazón no toca los paréntesis parece incorrecto. He editado mi pregunta para elaborar.sed 's/(127\.0\.1\.1)/IP \1/'
falla porque sed necesita ver\(
y\)
para la sintaxis de grupo, no(
y)
.