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"
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"
Réponses:
Pour remplacer la 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 "Expansion 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 The Open Group Technical Standard Base Specifications, Issue 7 , the Shell & Utilities volume, §2.6.2 "Parameter Expansion" .
\nque dans ce contexte se représenterait, pas une nouvelle ligne. Je n'ai pas juste à portée de main Bash maintenant à tester, mais vous devriez être capable d'écrire quelque chose comme $STRING="${STRING/$'\n'/<br />}". (Bien que vous souhaitiez probablement STRING//- remplacer tout - au lieu de juste STRING/.)
echo ${my string foo/foo/bar}. Vous auriez besoininput="my string foo"; echo ${input/foo/bar}
//directement, elle mentionne ce qui se passe "Si le modèle commence par ' /'" (ce qui n'est même pas exact, car le reste de cette phrase suppose que le supplément /ne fait pas réellement partie de le modèle) - mais je ne connais pas de meilleure source.
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 ne remplacera que 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"
Pour Dash, tous les messages précédents ne fonctionnent pas
La shsolution compatible POSIX est:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echoargument. Il fonctionne de manière trompeuse sans citer avec des chaînes simples, mais se casse facilement sur n'importe quelle chaîne d'entrée non triviale (espacement irrégulier, métacaractères shell, etc.).
essaye ça:
sed "s/Suzi/$secondString/g" <<<"$firstString"
Il vaut mieux utiliser bash que sedsi les chaînes ont des caractères RegExp.
echo ${first_string/Suzi/$second_string}
Il est portable pour Windows et fonctionne avec au moins aussi vieux que Bash 3.1.
Pour montrer que vous n'avez pas à vous soucier de vous échapper, tournons ceci:
/home/name/foo/bar
En cela:
~/foo/bar
Mais seulement si /home/namec'est au début. Nous n'avons pas besoin sed!
Étant donné que bash nous donne des variables magiques $PWDet $HOME, nous pouvons:
echo "${PWD/#$HOME/\~}"
EDIT: Merci pour Mark Haferkamp dans les commentaires pour la note sur la citation / l'évasion ~. *
Notez comment la variable $HOMEcontient des barres obliques mais cela n'a rien cassé.
Pour en savoir plus: Advanced Bash-Scripting Guide .
Si l'utilisation sedest indispensable, assurez-vous d' échapper à chaque personnage .
sedla pwdcommande pour éviter de définir une nouvelle variable à chaque $PS1exécution de ma commande personnalisée . Bash fournit-il un moyen plus général que les variables magiques d'utiliser la sortie d'une commande pour remplacer une chaîne? Quant à votre code, j'ai dû échapper au ~pour empêcher Bash de le développer dans $ HOME. De plus, que fait le #dans votre commande?
~": remarquez comment j'ai cité des trucs. N'oubliez pas de toujours citer des trucs! Et cela ne fonctionne pas seulement pour les variables magiques: toute variable est capable de substitutions, d'obtenir la longueur de chaîne, et plus, dans bash. Félicitations pour avoir essayé votre $PS1jeûne: vous pourriez également être intéressé $PROMPT_COMMANDsi vous êtes plus à l'aise dans un autre langage de programmation et que vous souhaitez coder une invite compilée.
echo "${PWD/#$HOME/~}"ne remplace pas mon $HOMEpar ~. Remplacer ~par \~ou '~'fonctionne. N'importe lequel de ces travaux sur Bash 4.2.53 sur une autre distribution. Pouvez-vous mettre à jour votre message pour citer ou échapper à la ~pour une meilleure compatibilité? Ce que je voulais dire par ma question "variables magiques" était: Puis-je utiliser la substitution de variables de Bash sur, par exemple, la sortie de unamesans l'enregistrer d'abord comme variable? Quant à mon personnel $PROMPT_COMMAND, c'est compliqué .
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.
Puisque 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}
Pur Posix méthode shell, qui , contrairement à Roman Kazanovskyi de sedréponse à base n'a pas besoin d'outils externes, à seulement propres natifs de la coquille expansions de paramètres . Notez que les noms de fichiers longs sont minimisés afin que le code s'adapte 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"
Production:
I love Sara and Marry
Comment ça fonctionne:
Supprimer le plus petit motif de suffixe. "${f%$t*}"renvoie " I love" si le suffixe $t" Suzi*" est dans $f" ". I love Suzi and Marry
Mais si t=Zelda, alors "${f%$t*}"ne supprime rien et renvoie la chaîne entière " I love Suzi and Marry".
Ceci est utilisé pour tester if $tis in $favec [ "${f%$t*}" != "$f" ]lequel sera évalué à true si la $fchaîne contient " Suzi*" et false sinon.
Si le test retourne vrai , construisez la chaîne souhaitée en utilisant Remove Smallest Suffix Pattern ${f%$t*} " I love" et Remove Smallest Prefix Pattern ${f#*$t} " and Marry", avec la 2ème chaîne $s" Sara" entre les deux.
Je sais que c'est vieux mais comme personne n'a mentionné l'utilisation de awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"