J'ai une chaîne qui peut contenir plusieurs espaces (et tabulations) et se terminer également par des espaces (mais elle ne commencera jamais par des espaces).
Quelque chose comme: "topo pippo pluto"
Je dois supprimer les espaces à la fin et remplacer toute séquence d'espaces restante par ~
. Dans l'exemple précédent, j'obtiendrais "topo~pippo~pluto"
.
Je le fais actuellement avec:
mystring=$(echo "$mystring" | sed -e 's/\s\s*/~/g' -e 's/~~*$//' )
3 Réponses :
Avec Bash:
$ shopt -s extglob $ str='topo pippo pluto ' $ str=${str%%+([[:blank:]])} $ echo "<$str>" <topo pippo pluto> $ str=${str//+([[:blank:]])/'~'} $ echo "<$str>" <topo~pippo~pluto>
L'option extglob
est requise pour activer le modèle + (pattern)
. $ {str %% + ([[: blank:]])}
supprime tous les espaces à la fin de la chaîne; $ {str // + ([[: blank:]]) / '~'}
remplace toutes les séries de blancs par un ~
.
p >
Utilisez + ([[: space:]])
pour remplacer les tabulations et espaces.
Merci! J'ai complètement raté l'existence d'extglob! Comme première transformation, j'ai dû ajouter str = $ {str // /}
(il y a un caractère de tabulation juste après les deux barres obliques) pour traiter les onglets. Ensuite, cela a parfaitement fonctionné!
@hmm Ou [[: blank:]]
- [[: space:]]
comprend quelques éléments supplémentaires en plus des blancs et des espaces.
Il est expliqué dans la documentation de bash
(exécutez man bash
sur votre terminal) sous la section "Extension des paramètres":
${parameter/pattern/string}
Substitution de modèle . Le
modèle
est développé pour produire un modèle comme dans l'expansion des chemins. LeParamètre
est développé et la plus longue correspondance depattern
par rapport à sa valeur est remplacée parstring
.
Sipattern
commence par/
, toutes les correspondances depattern
sont remplacées parstring
. Normalement, seule la première correspondance est remplacée.
Si lemodèle
commence par#
, il doit correspondre au début de la valeur développée duparamètre
.
Si lemotif
commence par%
, il doit correspondre à la fin de la valeur développée duparamètre
.
Sistring
est nul, les correspondances dumodèle
sont supprimées et le/
modèle suivant peut être omis.
Si le paramètre est@
ou*
, l'opération de substitution est appliquée à chaque paramètre de position à son tour, et le développement est la liste résultante.
Siparamètre
est une variable de tableau indicée avec@
ou*
, l'opération de substitution est appliquée à chaque membre du tableau à son tour, et l'expansion est la liste résultante.
Vous ne pouvez pas faire les deux remplacements en une seule commande, vous devez l'utiliser deux fois (une fois pour remplacer les séquences d'espaces par ~
et une fois pour supprimer le dernier ~
:
X="topo pippo pluto " # Enable the extended pattern matching shopt -s extglob # Replace the sequences of spaces with ~ Y="${X//+( )/\~}" echo "[$Y]" # prints: [topo~pippo~pluto~] # Replace the trailing ~ Z="${Y%\~}" echo "[$Z]" # prints: [topo~pippo~pluto]
Remarques:
echo
ci-dessus n'ont pas de signification particulière. Je les ai utilisés pour montrer clairement les limites des chaînes. ~
est un symbole spécial dans Bash et dans d'autres shells. Cela signifie le répertoire personnel de l'utilisateur et il est remplacé par sa valeur réelle. Il doit être échappé pour se représenter. + ()
est un motif étendu (cela signifie "un ou plusieurs des motifs présents entre parenthèses"); cela ne fonctionne que lorsque l'option shell extglob
est activée (en utilisant shopt
); apparemment, il est activé par défaut, mais dans les scripts, vous ne pouvez pas vous fier aux valeurs par défaut; vous feriez mieux de le configurer pour être sûr qu'il fonctionne; $ {Y% \ ~}
est une autre extension de paramètre (elle est également expliquée dans la documentation); il supprime de $ Y
le dernier suffixe correspondant ( ~
); comme expliqué ci-dessus, ~
doit être échappé ( \ ~
) pour être interprété comme lui-même et non comme le répertoire de base. Une solution shell POSIX:
#!/usr/bin/env sh mystring="topo pippo pluto " # Disable pathname expansion so the parameters expansion # will not capture pathes if mystring contains patterns set -f # Feed mystring as arguments list # where each space separated element (word) is an argument set -- $mystring # Restore pathname expansion set +f # Set ~ as the field separator IFS='~' # Expand the parameters into mystring with ~ as separator mystring="$*" # Restore the default field separator unset IFS echo "$mystring" # Print topo~pippo~pluto