Dans mon script bash, j'ai une chaîne externe (reçue de l'utilisateur) que je devrais utiliser dans le modèle sed.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
Comment puis-je échapper à la $REPLACE
chaîne afin qu'elle soit acceptée en toute sécurité par sed
comme remplacement littéral?
NOTE: Le KEYWORD
est une sous - chaîne muet sans allumettes , etc. Il n'est pas fournie par l' utilisateur.
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Réponses:
Avertissement : cela ne prend pas en compte les sauts de ligne. Pour une réponse plus approfondie, consultez plutôt cette question SO . (Merci, Ed Morton et Niklas Peter)
Notez que tout échapper est une mauvaise idée. Sed a besoin de beaucoup de personnages pour s'échapper pour obtenir leur signification particulière. Par exemple, si vous échappez un chiffre dans la chaîne de remplacement, il se transformera en une référence arrière.
Comme l'a dit Ben Blank, il n'y a que trois caractères à échapper dans la chaîne de remplacement (s'échappe eux-mêmes, barre oblique pour la fin de l'instruction et & pour tout remplacer):
Si jamais vous avez besoin de fuir
KEYWORD
chaîne, voici ce dont vous avez besoin:Et peut être utilisé par:
N'oubliez pas que si vous utilisez un caractère autre que
/
comme délimiteur, vous devez remplacer la barre oblique dans les expressions ci-dessus par le caractère que vous utilisez. Voir le commentaire de PeterJCLaw pour une explication.Modifié: en raison de certains cas d'angle précédemment non pris en compte, les commandes ci-dessus ont changé plusieurs fois. Consultez l'historique des modifications pour plus de détails.
la source
KEYWORD
, dans GNU sed , voici 2 autres caractères^
,$
non mentionnés ci-dessus:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
dans bash. Les guillemets doubles sont traités comme les "foo" et "bar" qui l'entourentLa commande sed vous permet d'utiliser d'autres caractères plutôt
/
que comme séparateur:Les guillemets doubles ne sont pas un problème.
la source
.
ce qui autrement aurait une signification particulière. J'ai modifié votre réponse.sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
avecsed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
et ça ne fait pas pareil.s
commande (comme en remplacement) de sed vous permet d'utiliser d'autres caractères au lieu de / comme séparateur. En outre, ce serait une réponse à la façon d'utiliser sed sur URL avec des barres obliques. Il ne répond pas à la question OP comment échapper une chaîne entrée par un utilisateur, qui pourrait contenir /, \, mais aussi # si vous décidez de l'utiliser. Et en plus, l'URI peut aussi contenir #Les trois seuls caractères littéraux traités spécialement dans la clause replace sont
/
(pour fermer la clause),\
(pour échapper les caractères, la référence arrière, etc.) et&
(pour inclure la correspondance dans le remplacement). Par conséquent, tout ce que vous devez faire est d'échapper à ces trois personnages:Exemple:
la source
Sur la base des expressions régulières de Pianosaurus, j'ai créé une fonction bash qui échappe à la fois au mot-clé et au remplacement.
Voici comment vous l'utilisez:
la source
man echo
), provoquant un comportement inattendu du tube lorsque votre argument$1
commence par un tiret. Au lieu de cela, vous pouvez commencer votre pipe avecprintf '%s\n' "$1"
.Il est un peu tard pour répondre ... mais il existe un moyen beaucoup plus simple de le faire. Modifiez simplement le délimiteur (c'est-à-dire le caractère qui sépare les champs). Donc, au lieu d'
s/foo/bar/
écrires|bar|foo
.Et voici la manière la plus simple de procéder:
La sortie résultante est dépourvue de cette clause DEFINER désagréable.
la source
&
et `` doit toujours être échappé, de même que le délimiteur, celui qui est choisi.$
dans la chaîne sur le point d'être modifiée et de conserver la signification de$
dans la chaîne de remplacement. dis que je veux changer$XXX
la valeur de variable$YYY
,sed -i "s|\$XXX|$YYY|g" file
fonctionne très bien.Il s'avère que vous posez la mauvaise question. J'ai également posé la mauvaise question. La raison pour laquelle c'est faux est le début de la première phrase: "Dans mon script bash ...".
J'avais la même question et j'ai fait la même erreur. Si vous utilisez bash, vous n'avez pas besoin d'utiliser sed pour effectuer des remplacements de chaîne (et c'est beaucoup plus propre d'utiliser la fonction de remplacement intégrée à bash).
Au lieu de quelque chose comme, par exemple:
vous pouvez utiliser exclusivement les fonctionnalités bash:
la source
$A
et$B
n'est pas cité, mais ce n'est pas le cas. Les guillemets à l'intérieur du${}
ne correspondent pas aux guillemets à l'extérieur de celui-ci.var='has space'
) -OUTPUT=${INPUT//"$A"/"$B"}
c'est sûr.Utilisez awk - c'est plus propre:
la source
awk
c'est qu'il n'a rien de similairesed -i
, ce qui est extrêmement pratique 99% du temps.Voici un exemple d'un AWK que j'ai utilisé il y a quelque temps. Il s'agit d'un AWK qui imprime de nouveaux AWKS. AWK et SED étant similaires, cela peut être un bon modèle.
Cela semble excessif, mais d'une manière ou d'une autre cette combinaison de guillemets fonctionne pour garder le 'imprimé en tant que littéraux. Ensuite, si je me souviens bien, les variables sont simplement entourées de guillemets comme celui-ci: "$ 1". Essayez-le, faites-moi savoir comment cela fonctionne avec SED.
la source
J'ai une amélioration par rapport à la fonction sedeasy, qui rompra avec les caractères spéciaux comme tab.
Alors, qu'est-ce qui est différent?
$1
et$2
entouré de guillemets pour éviter les expansions du shell et préserver les tabulations ou les espaces doubles.Tuyauterie supplémentaire
| sed -e 's:\t:\\t:g'
(j'aime:
comme jeton) qui transforme un onglet en\t
.la source
Voici les codes d'échappement que j'ai trouvés:
la source
n'oubliez pas tout le plaisir qui se produit avec la limitation de la coque autour de "et"
donc (en ksh)
la source
Si vous cherchez simplement à remplacer la valeur de variable dans la commande sed, supprimez simplement l'exemple:
la source
Si le cas se trouve être que vous générez un mot de passe aléatoire à passer pour
sed
remplacer le modèle, alors vous choisissez de faire attention à quel ensemble de caractères dans la chaîne aléatoire. Si vous choisissez un mot de passe créé en encodant une valeur en base64, il n'y a qu'un seul caractère qui est à la fois possible en base64 et également un caractère spécial dans lesed
modèle de remplacement. Ce caractère est "/" et est facilement supprimé du mot de passe que vous générez:la source
Un moyen plus simple de le faire consiste simplement à créer la chaîne avant la main et à l'utiliser comme paramètre pour
sed
la source
REPLACE=/
donnesed: -e expression #1, char 12: unknown option to `s'