Question Remplacer une sous-chaîne pour une autre chaîne dans un 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 ceci:

firstString="I love Sara and Marry"

438
2017-11-03 16:01


origine


Réponses:


Pour remplacer le premier occurrence d'un motif avec une chaîne donnée, utilisez ${paramètre/modèle/chaîne}:

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

Remplacer tout occurrences, utilisation ${paramètre//modèle/chaîne}:

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

(Ceci est documenté dans la Bash Manuel de référence, §3.5.3 "Expansion des paramètres d'enveloppe".)

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 Les spécifications de base de la norme technique Open Group, numéro 7, la Shell et utilitaires volume, §2.6.2 "Expansion des paramètres".


726
2017-11-03 16:05



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

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

Cela ne remplacera que la première occurrence; pour les remplacer tous, doublez le premier slash:

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

128
2017-11-03 16:05



essaye ça:

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

45
2017-11-03 16:04



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 à Windows et fonctionne avec au moins aussi vieux que Bash 3.1.

Pour montrer que vous n'avez pas à vous soucier de vous échapper, passons à ceci:

/home/name/foo/bar

Dans ceci:

~/foo/bar

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

Étant donné que bash nous donne des variables magiques $PWD et $HOME, nous pouvons:

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

MODIFIER: Merci à Mark Haferkamp dans les commentaires pour la note sur la citation / la fuite ~*

Notez comment la variable $HOME contient des barres obliques mais cela n'a rien cassé.

En lire plus: Guide avancé de script Bash.
Si vous utilisez sed est un must, assurez-vous de échapper à chaque personnage.


38
2018-06-22 03:43



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

Le POSIX sh solution compatible est:

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

25
2018-04-09 08:56



Si demain vous décidez de ne pas aimer Marry, vous pouvez aussi la remplacer:

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.


7
2017-07-11 02:39