181 votes

Comment insérer des chaînes de caractères contenant des slashs avec sed ?

J'ai un projet Visual Studio, qui est développé localement. Les fichiers de code doivent être déployés sur un serveur distant. Le seul problème, ce sont les URL qu'ils contiennent, qui sont codées en dur.

Le projet contient des URL telles que ?page=one . Pour que le lien soit valide sur le serveur, il doit être /page/one .

J'ai décidé de remplacer toutes les URL dans mes fichiers de code par sed avant le déploiement, mais je suis bloqué par les barres obliques.

Je sais que cette solution n'est pas très jolie, mais elle est simple et me ferait gagner beaucoup de temps. Le nombre total de chaînes de caractères que je dois remplacer est inférieur à 10. Le nombre total de fichiers qui doivent être vérifiés est de ~30.

Voici un exemple décrivant ma situation :

Commande que j'utilise :

sed -f replace.txt < a.txt > b.txt

replace.txt qui contient toutes les chaînes de caractères :

s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g

a.txt :

?page=one&
?page=two&
?page=three&

Contenu de b.txt après avoir exécuté ma commande sed :

pageone
pagetwo
pagethree

Ce que je veux b.txt à contenir :

/page/one
/page/two
/page/three

324voto

lurker Points 16947

Le plus simple serait d'utiliser un délimiteur différent dans vos lignes de recherche/remplacement, par exemple :

s:?page=one&:pageone:g

Vous pouvez utiliser comme délimiteur tout caractère qui ne fait partie d'aucune des deux chaînes. Ou bien, vous pouvez l'échapper avec une barre oblique inverse :

s/\//foo/

Qui remplacerait / avec foo . Vous voudrez utiliser la barre oblique inversée échappée dans les cas où vous ne savez pas quels caractères peuvent apparaître dans les chaînes de remplacement (s'il s'agit de variables shell, par exemple).

125voto

Tom Anderson Points 22456

El s peut utiliser n'importe quel caractère comme délimiteur ; le caractère qui suit la commande s est utilisé. J'ai été élevé pour utiliser un # . Comme ça :

s#?page=one&#/page/one#g

78voto

John Zwinck Points 43636

Un fait très utile mais moins connu à propos de sed est que le familier s/foo/bar/ peut utiliser n'importe quelle ponctuation, pas seulement des barres obliques. Une alternative courante est s@foo@bar@ Il en ressort que la solution à votre problème est évidente.

12voto

Ilja Points 644

Ajouter \ avant les caractères spéciaux :

s/\?page=one&/page\/one\//g

etc.

5voto

Yoav Drori Points 51

Dans un système que je suis en train de développer, la chaîne de caractères à remplacer par sed est le texte d'entrée d'un utilisateur qui est stocké dans une variable et passé à sed.

Comme indiqué précédemment dans ce billet, si la chaîne de caractères contenue dans le bloc de commande sed contient le délimiteur réel utilisé par sed - alors sed se termine sur une erreur de syntaxe. Considérons l'exemple suivant :

Ça marche :

$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345

Cette pause :

$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'

Remplacer le délimiteur par défaut n'est pas une solution robuste dans mon cas, car je ne voulais pas empêcher l'utilisateur de saisir des caractères spécifiques utilisés par sed comme délimiteur (par exemple "/").

Cependant, l'échappement de toutes les occurrences du délimiteur dans la chaîne d'entrée résoudrait le problème. Considérez la solution ci-dessous qui consiste à échapper systématiquement le caractère de délimitation dans la chaîne d'entrée avant qu'elle ne soit analysée par sed. Un tel échappement peut être implémenté comme un remplacement en utilisant sed lui-même, ce remplacement est sûr même si la chaîne d'entrée contient le délimiteur - puisque la chaîne d'entrée ne fait pas partie du bloc de commande sed :

$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6

J'ai converti ceci en une fonction à utiliser par divers scripts :

escapeForwardSlashes() {

     # Validate parameters
     if [ -z "$1" ]
     then
             echo -e "Error - no parameter specified!"
             return 1
     fi

     # Perform replacement
     echo ${1} | sed -e "s#/#\\\/#g"
     return 0
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X