erreur sed: "référence non valide \ 1 sur le RHS de la commande` s '"

104

J'exécute plusieurs commandes de substitution au cœur d'un script colorize pour maven . L'une des sedcommandes utilise une expression régulière qui fonctionne dans le shell comme indiqué ici . L'implémentation actuelle (qui ne fonctionne pas) peut être trouvée ici .

Lorsque j'inclus l'une des variantes de la commande dans le script, un comportement différent se produit:

Variante 1:

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

Adapté au script:

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

Erreur: le shell génère les mêmes informations que si je tapais $ sed. Étrange!?


Variante 2:

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

Adapté au script:

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

Erreur:

sed: -e expression # 7, char 59: référence \ 1 invalide sur le RHS de la commande `s '

JJD
la source
10
Dans mon cas, j'avais combiné une -i(option d'édition sur place) avec -re, résultant en -ire(ce qui -iconsommait le refragment comme SUFFIXargument et donc le mode regex étendu n'était pas activé); le changer pour -i -rerésoudre le problème.
Janaka Bandara
Il est également à noter que les guillemets simples 'et doubles "sont traités légèrement différemment, en particulier lors de l'interprétation $vars. Par exemple: sudo sh -c "sed -r -i 's/(^.+_supplicant.conf)/\1${MTXT}/' /etc/network/interfaces"fonctionne, mais: sudo sh -c 'sed -r -i "s/(^.+_supplicant.conf)/\1${MTXT}/" /etc/network/interfaces'ne fonctionne pas.
not2qubit

Réponses:

52

N'avez-vous pas besoin de capturer pour que cela fonctionne? c'est-à-dire pour la variante 2:

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

(Remarque: non testé)

Sans l'argument -r, les références arrière (comme \ 1) ne fonctionneront pas.

Denis de Bernardy
la source
42
L' -roption de sed semble être nécessaire pour que la référence arrière fonctionne. Par exemple, sed -e 's/([[:digit:]])/is a digit/'fonctionne mais sed -e 's/([[:digit:]])/\1 is a digit/produit l'erreur d'origine sans -rsed. REMARQUE: le premier appel de sed recherche un littéral (<digit>)et n'est pas un groupe de capture.
Andrew Falanga
Le commentaire sous la réponse est en fait une réponse. Vous pouvez peut-être modifier votre réponse pour la refléter.
miroxlav
@AndrewFalanga vous auriez dû poster votre commentaire en réponse
sanmai
2
Jamais mon erreur a été d'utiliser -ireau lieu d'utiliser -ri. La commande compte :-)
m3nda
54

Cette erreur est courante pour les parenthèses qui ne sont pas échappées. Échappez-les et réessayez.


Par exemple:

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

Doit être échappé avec des barres obliques inverses avant chaque parenthèse:

/^$/b
:loop
$!{
N
/\n$/!b loop
}
s/\n\(.\)/\1/g
e18r
la source
6
Attention, si vous utilisez -rvous n'avez pas à échapper les parenthèses.
qräbnö
13

Si l' option -r/ --regexp-extendedn'est pas fournie, les parenthèses de capture doivent être échappées.

OrangeDog
la source
5

Vous avez besoin de vous échapper /après le.

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

Ou si vous ne voulez pas vous soucier de vous échapper, utilisez |

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

ÉDITER:

sed -e "s|WARNING: \([a-zA-Z0-9.-/\\ :]+\)|${warn}WARNING: \1${c_end}|g"
slackmart
la source
Cela semble raisonnable. Mais cela ne fonctionne pas dans le contexte du script.
JJD
Désolé. La modification soulève l'erreur: sed: -e expression #7, char 58: Invalid range end. La réponse de @Denis fonctionne.
JJD
2
Ok, puis +1 pour la réponse de
@Denis