web-dev-qa-db-fra.com

Remplacer une sous-chaîne par une autre chaîne dans le script Shell

J'ai "J'aime Suzi et Marry" et je veux changer "Suzi" en "Sara".

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...

Le résultat doit être comme ça:

firstString="I love Sara and Marry"
647
Zincode

Pour remplacer la première première occurrence d'un modèle par une chaîne donnée, utilisez ${parameter/pattern/string}:

#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"    
# prints 'I love Sara and Marry'

Pour remplacer toutes les occurrences , utilisez ${parameter//pattern/string}:

message='The secret code is 12345'
echo "${message//[0-9]/X}"           
# prints 'The secret code is XXXXX'

(Ceci est documenté dans le Manuel de référence Bash , §3.5.3 "Développement des paramètres du shell" .)

Notez que cette fonctionnalité n'est pas spécifiée par POSIX - c'est une extension Bash - donc tous les shells Unix ne l'implémentent pas. Pour la documentation POSIX pertinente, voir Spécifications de base de la norme technique du groupe Open, numéro 7 , le Shell & Utilities volume, §2.6.2 "Extension des paramètres" .

1066
ruakh

Cela peut être fait entièrement avec la manipulation de chaîne bash:

first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}

Cela remplacera seulement la première occurrence; pour les remplacer tous, doublez la première barre oblique:

first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
168
Kevin

essaye ça:

 sed "s/Suzi/$secondString/g" <<<"$firstString"
59
Kent

Pour Dash, tous les posts précédents ne fonctionnent pas

La solution compatible POSIX sh est:

result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
50

Il vaut mieux utiliser bash que sed si les chaînes ont des caractères RegExp.

echo ${first_string/Suzi/$second_string}

Il est portable pour Windows et fonctionne avec au moins le même âge que Bash 3.1.

Pour montrer que vous n'avez pas à vous soucier de votre échappatoire, tournons-nous à ceci:

/home/name/foo/bar

Dans ceci:

~/foo/bar

Mais seulement si /home/name est au début. Nous n'avons pas besoin de sed!

Etant donné que bash nous donne les variables magiques $PWD et $HOME, nous pouvons:

echo "${PWD/#$HOME/\~}"

EDIT: Merci à Mark Haferkamp dans les commentaires de la note citant/échappant ~. *

Notez que la variable $HOME contient des barres obliques sans que rien ne se casse.

Pour en savoir plus: Advanced Bash-Scripting Guide .
Si vous devez utiliser sed, assurez-vous de échappe tous les caractères .

44
Camilo Martin

Si demain vous décidez que vous n'aimez pas Marry, elle peut également être remplacée:

today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt

Il doit y avoir 50 façons de quitter votre amoureux.

18
Josh Habdas

Depuis je ne peux pas ajouter de commentaire. @ruaka Pour rendre l'exemple plus lisible, écrivez-le comme ceci

full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
4
Nate Revo

Pure POSIX Méthode Shell, qui contrairement à réponse de --- (la réponse de Roman Kazanovskyi de sed- ) == n'a besoin d'aucun outil externe, mais uniquement du natif de Shell - extensions de paramètres . Notez que les noms de fichier longs sont minimisés afin que le code tienne mieux sur une seule ligne:

_f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"
_

Sortie:

_I love Sara and Marry
_

Comment ça fonctionne:

  • Supprimer le plus petit modèle de suffixe. _"${f%$t*}"_ renvoie "I love" si le suffixe _$t_ "Suzi*" est in _$f_ " I loveSuzi and Marry ".

  • Mais si _t=Zelda_, alors _"${f%$t*}"_ ne supprime rien et renvoie la chaîne complète "I love Suzi and Marry".

  • Ceci est utilisé pour tester si _$t_ est dans _$f_ avec _[ "${f%$t*}" != "$f" ]_ qui sera évalué à true si la chaîne _$f_ contient "Suzi* "et false sinon.

  • Si le test renvoie true, créez la chaîne souhaitée à l'aide de Supprimer le plus petit modèle de suffixe _${f%$t*}_ "I love" et - Supprimer le plus petit modèle de préfixe _${f#*$t}_ "and Marry", avec le 2nd chaîne _$s_ "Sara "entre les deux.

1
agc