Je remplace, à partir d'un titre de flux, tous les caractères sauf les lettres et les chiffres par un tiret pour utiliser le résultat comme nom de fichier sûr pour tout système de fichiers:
$ t="Episodie 06: No hope of riding home (NEW) - Advanced grammar"
$ echo ${t//[^A-Za-z0-9]/-}
Episodie-06--No-hope-of-riding-home--NEW----Advanced-grammar
Cependant, je voudrais condenser tous les tirets répétitifs avec un seul comme Episodie-06-No-hope-of-riding-home-NEW-Advanced-grammar
J'ai trouvé que je peux y arriver en utilisant une substitution en deux passes:
$ t="Episodie 06: No hope of riding home (NEW) - Advanced grammar"
$ tmp=${t//[^A-Za-z0-9]/-}
$ echo ${tmp//--/-}
Episodie-06-No-hope-of-riding-home-NEW--Advanced-grammar
Je pensais pouvoir le faire en un seul passage comme:
$ echo ${t//[^A-Za-z0-9]+/-}
mais ça ne marche pas.
Un indice?
Remarque: je ne veux pas aller avec sed
ou d'autres outils
shopt
coquilles qui le supportent.shopt
est spécifique à bash. La syntaxe de modèle qu'il active est toujours disponible dans toutes les variantes de ksh. Dans zsh, cette syntaxe doit être activée avecsetopt ksh_glob
. POSIX n'a pas une telle fonctionnalité, ses caractères génériques sont moins puissants que les regexps. Les coquilles autres que bash / ksh / zsh, qui dans la pratique signifie principalement cendre de nos jours, ont tendance à coller aux caractères génériques POSIX.echo "$t" | sed -r 's/[^[:alnum:]]+/-/g; s/^-|-$//'
. J'accepte votre réponse car elle fait exactement ce qui a été demandé.${var/PATTERN/REPLACEMENT}
construction est également spécifique à ksh / bash / zsh.sed
car je connais mieux sa syntaxe et son comportement, je peux facilement ajouter une instruction pour supprimer les tirets de début / fin, je n'ai pas besoin de me soucier du caractère\n
. Est-cesed
beaucoup moins disponible quetr
?tr
est un bon outil pour ce travailla source
tr
... Cependant, j'essayais de le faire dans Bash, sinon j'irais avecsed
:echo "$t" | sed -r 's/[^A-Za-z0-9]+/-/g'
Note: I don't want to go with sed or other tools
Si vous voulez rester avec pure bash, vous devrez vous contenter de la solution à deux passes. Les substitutions de chaînes basiques utilisent des globes , comme dans l'expansion des chemins d'accès, et non des expressions régulières. Les seuls caractères spéciaux sont globs
*
,?
et[]
dont les équivalents bruts dans les expressions régulières sont.*
,.
et[]
. Jetez un œil au wiki Wooledge et aux sections de la page de manuel sur et pour plus d'informations.bash(1)
Parameter Expansion
Pathname Expansion
Tout comme un commentaire, une expansion en deux passes en bash pur est toujours plus rapide que d'essayer de faire la même chose en invoquant un programme externe, donc je ne m'inquiéterais pas trop.
la source
shopt -s extglob; t="${t//+([^A-Za-z0-9])/-}"