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" .
\n
que 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 sh
solution compatible POSIX est:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
argument. 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 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 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/name
c'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/\~}"
EDIT: Merci pour Mark Haferkamp dans les commentaires pour la note sur la citation / l'évasion ~
. *
Notez comment la variable $HOME
contient des barres obliques mais cela n'a rien cassé.
Pour en savoir plus: Advanced Bash-Scripting Guide .
Si l'utilisation sed
est indispensable, assurez-vous d' échapper à chaque personnage .
sed
la pwd
commande pour éviter de définir une nouvelle variable à chaque $PS1
exé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 $PS1
jeûne: vous pourriez également être intéressé $PROMPT_COMMAND
si 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 $HOME
par ~
. 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 uname
sans 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 sed
ré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 $t
is in $f
avec [ "${f%$t*}" != "$f" ]
lequel sera évalué à true si la $f
chaî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"