J'aimerais utiliser sed
pour échapper à toutes les occurrences non échappées d'un caractère, par exemple "&", dans une chaîne contenue dans la variable text
. Ce que je fais c'est
text='one&two\&three'
sed 's/\([^\\]\)&/\1\\&/g' <<< "${text}"
et j'attends que la sortie soit one\&two\&three
. Cependant, ce que je reçois est
one\e&two\&three
Ce que je (essaie de) faire:
\([^\\]\)&
doit correspondre à toute occurrence de &
non précédé d'une barre oblique inversée et stocker le caractère qui précède &
dans \1
\1\\&
devrait mettre une barre oblique inverse entre &
et le caractère précédent, mais il agit comme \\\1&
pour une raison étrangeQu'est-ce que je fais mal ici?
Pourquoi votre commande échoue:
Tu l'as fait:
sed 's/\([^\\]\)&/\1\\&/g' <<< "${text}"
[^\\]\
correspond à n'importe quel caractère sauf \
, et le place dans le groupe 1 correspondant, puis &
correspond à un littéral &
. Donc, pour one&two\&three
, cela correspond à e
avant le premier &
, placez-le dans le groupe capturé 1. Pour le &
avant three
, cela ne correspond pas. comme \
est avant &
Dans le remplacement, vous avez utilisé \1\\&
, la sortie devient donc one\e&two\&three
car:
\1
est remplacé par e
\\
s sont traités comme un seul \
. cela nous donne e\
jusqu'à maintenant&
correspondra à la correspondance complète c'est-à-dire e&
c'est-à-dire &
ne sera pas échappé comme vous le pensiezAinsi, la partie correspondante, à savoir e&
est remplacée par e\e&
Vous obtiendrez le résultat souhaité si vous utilisiez un autre \
avant &
(Comme deux \\
en font un \
, vous en aurez donc besoin avant &
:
sed 's/\([^\\]\)&/\1\\\&/g' <<<"${text}"
Comme sed
d'Ubuntu prend en charge ERE (expression régulière étendue), vous pouvez utiliser l'option -E
ou -r
pour l'activer afin de supprimer le ()
s lors de la capture:
sed -E 's/([^\\])&/\1\\\&/g' <<<"${text}"
Autre approche:
Tout d'abord, supprimez \
s avant tout &
s, puis ajoutez \
avant tout &
:
sed -E 's/[\]+(&)/\1/g; s/&/\\&/g'
Ceci est composé de deux déclarations sed
:
s/[\]+(&)/\1/g
supprime tous les \
s avant &
de la chaîne (ligne)
s/&/\\&/g
ajoute un \
trop à tous &
dans la chaîne (ligne)
Exemple:
% text='one&two\&three'
% sed 's/\([^\\]\)&/\1\\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/([^\\])&/\1\\\&/g' <<< "${text}"
one\&two\&three
% sed -E 's/[\]+(&)/\1/g; s/&/\\&/g' <<<"$text"
one\&two\&three