error de sed: "referencia inválida \ 1 en el RHS del comando` s '"

103

Ejecuto varios comandos de sustitución como el núcleo de un script de colorize para maven . Uno de los sedcomandos utiliza una expresión regular que funciona para buscar en el shell como se explica aquí . La implementación actual (que no funciona) se puede encontrar aquí .

Cuando incluyo una de las variantes del comando en el script, ocurre un comportamiento diferente:

Variante 1:

$ sed -re "s/([a-zA-Z0-9./\\ :-]+)/\1/g"

Adaptado al guión:

-re "s/WARNING: ([a-zA-Z0-9./\\ :-]+)/${warn}WARNING: \1${c_end}/g" \

Error: el shell genera la misma información que si escribiera $ sed. ¿¡Extraño!?


Variante 2:

$ sed -e "s/\([a-zA-Z0-9./\\ :-]\+\)/\1/g"

Adaptado al guión:

-e "s/WARNING: \([a-zA-Z0-9./\\ :-]\+\)/${warn}WARNING: \1${c_end}/g" \

Error:

sed: -e expresión # 7, char 59: referencia inválida \ 1 en el RHS del comando `s '

JJD
fuente
10
En mi caso, combiné una -i(opción de editar en el lugar) con -re, lo que resultó en -ire(de modo que -iconsumía el refragmento como SUFFIXargumento y, por lo tanto, no se habilitaba el modo de expresión regular extendida); cambiándolo para -i -resolucionar el problema.
Janaka Bandara
También es importante notar que las comillas simples 'y las comillas dobles "se tratan de manera ligeramente diferente, especialmente al interpretar $vars. Por ejemplo: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces"funciona, pero: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces'no.
not2qubit

Respuestas:

51

¿No necesitas capturar para que funcione? es decir, para la variante 2:

-r -e "s/WARNING: (\([a-zA-Z0-9./\\ :-]\+\))/${warn}WARNING: \1${c_end}/g" \

(Nota: no probado)

Sin el argumento -r, las referencias inversas (como \ 1) no funcionarán.

Denis de Bernardy
fuente
42
La -ropción de sed parece ser necesaria para que funcione la referencia inversa. Por ejemplo, sed -e 's/([[:digit:]])/is a digit/'funciona pero sed -e 's/([[:digit:]])/\1 is a digit/produce el error original sin -rsed. NOTA: la primera invocación de sed busca un literal (<digit>)y no es un grupo de captura.
Andrew Falanga
El comentario debajo de la respuesta es en realidad una respuesta. Tal vez puedas editar tu respuesta para reflejarla.
miroxlav
@AndrewFalanga, debería haber publicado su comentario como respuesta
sanmai
2
No importa, mi error fue usar en -irelugar de usar -ri. El pedido importa :-)
m3nda
54

Este error es común para los paréntesis que no tienen escape. Escapa de ellos y vuelve a intentarlo.


Por ejemplo:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n(.)/\1/g

Debe escaparse con barras invertidas antes de cada paréntesis:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g
e18r
fuente
6
Atención, si usa -rno tiene que escapar del paréntesis.
qräbnö
13

Si no se proporciona la opción -r/ --regexp-extended, entonces se deben escapar los paréntesis de captura.

OrangeDog
fuente
5

Necesitas escapar /después de la.

sed -e "s/\([a-zA-Z0-9.\/\\ :-]\+\)/\1/g"

O si no quiere preocuparse por escapar, use |

sed -e "s|\([a-zA-Z0-9./\\ :-]\+\)|\1|g"

EDITAR:

sed -e "s|WARNING: \([a-zA-Z0-9.-/\\ :]+\)|${warn}WARNING: \1${c_end}|g"
slackmart
fuente
Suena razonable. Pero no funciona en el contexto del guión.
JJD
Lo siento. La edición plantea el error: sed: -e expression #7, char 58: Invalid range end. La respuesta de @Denis funciona.
JJD
2
Ok, entonces +1 para la respuesta de
@Denis