web-dev-qa-db-fra.com

Comment remplacer les chaînes contenant des slash 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 est l’URL qu’ils contiennent qui sont codés en dur.

Le projet contient des URL telles que? Page = one . Pour que le lien soit valide sur le serveur, il doit s'agir de/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 des barres obliques.

Je sais que ce n’est pas une belle solution, mais c’est simple, cela me ferait gagner beaucoup de temps. Le nombre total de chaînes que je dois remplacer est inférieur à 10. Le nombre total de fichiers à vérifier est d'environ 30.

Exemple décrivant ma situation est ci-dessous:

Commande que j'utilise:

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

replace.txt qui contient toutes les chaînes:

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 que b.txt contienne:

/page/one
/page/two
/page/three
113
afaf12

Le moyen le plus simple consiste à utiliser un délimiteur différent dans vos lignes de recherche/remplacement, par exemple:

s:?page=one&:pageone:g

Vous pouvez utiliser n'importe quel caractère comme délimiteur ne faisant pas partie de l'une ou l'autre chaîne. Ou, vous pouvez y échapper avec une barre oblique inverse.

223
lurker

La commande s peut utiliser n’importe quel caractère comme délimiteur; quel que soit le caractère qui vient après la s est utilisé. J'ai été amené à utiliser un #. Ainsi:

s#?page=one&#/page/one#g
83
Tom Anderson

Un fait très utile mais peu connu à propos de sed est que la commande s/foo/bar/ bien connue peut utiliser n'importe quelle ponctuation, pas seulement des barres obliques. Une alternative courante est s@foo@bar@, à partir de laquelle il devient évident de résoudre votre problème.

51
John Zwinck

ajouter\avant les caractères spéciaux

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

etc

5
Ilja

Dans un système que je développe, la chaîne à remplacer par sed est le texte saisi par un utilisateur, qui est stocké dans une variable et passé à sed.

Comme indiqué précédemment dans cet article, si la chaîne contenue dans le bloc de commandes sed contient le délimiteur utilisé par sed - alors sed se termine en cas d'erreur de syntaxe. Prenons l'exemple suivant:

Cela marche:

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

Cela casse:

$ 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, le fait d'échapper à toute occurrence du délimiteur dans la chaîne d'entrée résoudrait le problème . Considérez la solution ci-dessous consistant à échapper systématiquement le caractère de délimiteur dans la chaîne d'entrée avant de le faire analyser par sed . un remplacement utilisant sed lui-même, ce remplacement est sûr même si la chaîne d'entrée contient le délimiteur - c'est parce que 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 cela 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
}
4
Yoav Drori

cette ligne devrait fonctionner pour vos 3 exemples:

sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
  • J'ai utilisé -r pour économiser de l'échappement.
  • la ligne devrait être générique pour votre un, deux trois cas. vous n'avez pas à faire le sous 3 fois

testez avec votre exemple (a.txt):

kent$  echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three
3
Kent

sed est le s tream ed itor , en ce sens que vous pouvez utiliser | (pipe) pour envoyer flux standard (STDIN et STDOUT spécifiquement) à travers sed et les modifier par programmation à la volée, ce qui en fait un outil pratique dans la tradition de la philosophie Unix; mais peut aussi éditer directement des fichiers en utilisant le paramètre -i mentionné ci-dessous.
Considérer ce qui suit:

sed -i -e 's/few/asd/g' hello.txt

s/ est utilisé pour s pour remplacer l'expression trouvée few avec asd:

Les rares, les courageux.


Les asd, les braves.

/g signifie "global", ce qui signifie faire ceci pour toute la ligne. Si vous laissez le /g (avec s/few/asd/, il doit toujours y avoir trois barres obliques quoi qu'il en soit) et que few apparaisse deux fois sur la même ligne, seule la première few est remplacée par asd:

Les rares hommes, les rares femmes, les braves.


Les hommes, les rares femmes, les braves.

Ceci est utile dans certaines circonstances, par exemple pour modifier des caractères spéciaux au début des lignes (par exemple, remplacer les symboles plus grands que certaines personnes utilisent pour citer le contenu précédent dans les fils de courrier électronique avec un onglet horizontal tout en laissant une inégalité algébrique citée plus tard dans la ligne. intact), mais dans votre exemple où vous spécifiez que n'importe oùfew doit être remplacé, assurez-vous que vous avez bien ce /g.

Les deux options suivantes (drapeaux) sont combinées en une, -ie:

L'option -i permet d'éditer i n une place sur le fichier hello.txt.

L'option -e indique la commande e xpression/à exécuter, dans ce cas s/.

Remarque: Il est important que vous utilisiez -i -e pour rechercher/remplacer. Si vous faites -ie, vous créez une sauvegarde de chaque fichier avec la lettre 'e' ajoutée.

2
Chaminda Bandara

replace.txt devrait être 

s/?page=/\/page\//g
s/&//g
1
Ion Cojocaru

Grande réponse de Anonymous.\J'ai résolu mon problème en essayant d'échapper aux guillemets dans les chaînes HTML.

Donc, si vous utilisez sed pour renvoyer des modèles HTML (sur un serveur), utilisez une double barre oblique inversée au lieu de single:

var htmlTemplate = "<div style=\\"color:green;\\"></div>";
1
Sirar Salih

Une alternative plus simple consiste à utiliser AWK comme cette réponse

awk '$0="prefix"$0' file > new_file

0
Mark