erro sed: “referência inválida \ 1 no RHS do comando` s '”

104

Eu executo vários comandos de substituição como o núcleo de um script colorize para maven . Um dos sedcomandos usa uma expressão regular que funciona e se encontra no shell, conforme discutido aqui . A implementação atual (não funcionando) pode ser encontrada aqui .

Quando incluo uma das variantes do comando no script, ocorre um comportamento diferente:

Variante 1:

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

Adaptado ao roteiro:

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

Erro: o shell exibe as mesmas informações que se eu digitaria $ sed. Estranho!?


Variante 2:

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

Adaptado ao roteiro:

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

Erro:

sed: -e expressão # 7, char 59: referência inválida \ 1 no RHS do comando `s '

JJD
fonte
10
No meu caso, eu tinha combinado a -i(opção editar no local) com -re, resultando em -ire(de modo que -iestava consumindo o refragmento como seu SUFFIXargumento e, portanto, o modo regex estendido não estava sendo ativado); alterá-lo para -i -recorrigir o problema.
Janaka Bandara
É importante notar também que as aspas simples 'e duplas "são tratadas de maneira ligeiramente diferente, especialmente na interpretação $vars. Por exemplo: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces"funciona, mas: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces'não.
not2qubit

Respostas:

52

Você não precisa realmente capturar para que funcione? ou seja, para a variante 2:

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

(Nota: não testado)

Sem o argumento -r, as referências anteriores (como \ 1) não funcionarão.

Denis de Bernardy
fonte
42
A -ropção sed parece ser necessária para que a referência anterior funcione. Por exemplo, sed -e 's/([[:digit:]])/is a digit/'funciona, mas sed -e 's/([[:digit:]])/\1 is a digit/produz o erro original sem -rsed. NOTA: a primeira chamada de sed procura um literal (<digit>)e não é um grupo de captura.
Andrew Falanga
O comentário abaixo da resposta é na verdade uma resposta. Talvez você possa editar sua resposta para refleti-la.
miroxlav,
@AndrewFalanga você deveria ter postado seu comentário como uma resposta
sanmai
2
Não importa, meu erro foi usar em -irevez de usar -ri. O pedido é importante :-)
m3nda
54

Este erro é comum para parênteses sem escape. Fuja deles e tente novamente.


Por exemplo:

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

Deve ser escapado com barras invertidas antes de cada parêntese:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g
e18r
fonte
6
Atenção, se você usar -rnão precisa escapar dos parênteses.
qräbnö
13

Se a opção -r/ --regexp-extendednão for fornecida, os parênteses de captura devem ser escapados.

OrangeDog
fonte
5

Você precisa escapar do /depois do.

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

Ou se você não quiser se preocupar em 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
fonte
Parece razoável. Mas não funciona no contexto do script.
JJD
Desculpe. A edição levanta o erro: sed: -e expression #7, char 58: Invalid range end. A resposta de @Denis funciona.
JJD de
2
Ok, então +1 para a resposta de
@Denis