Filtrage de chaîne de caractères en Shell

Menu principal

Voici un snippet qui permet de filtrer et de transformer une chaîne de caractères afin de pouvoir l’utiliser dans une URL ou pour un nom de fichier ou de répertoire.

Il a été testé avant tout sous Bash mais ne devrait pas poser de problèmes particulier pour son poartage sous d’autres Shell excepté pour l’option -n de la commande echo.

Intérêt

Ce snippet permet de s’assurer qu’une chaîne de caractères pourra être utilisée dans la construction d’une URL ou d’un nom de fichier ou de répertoire.

Son intérêt principal réside dans le niveau de sécurité qu’elle autorise vis-à-vis de données fournies par les utilisateurs.

Il permet aussi de créer des URL propres sans accents, majuscules, espaces ou caractères spéciaux (/, &, + etc.)

Pré-requis

La commande iconv doit être installée et accessible au script.

Hormis cette commande, seule la commande tr est utilisée mais celle-ci est un standard sous Unix.

Fonctionnement

Le snippet consiste en une succession de tubes/pipes.

La chaîne générée ne sera composée que de lettres minuscules non accentuées et de tirets '-'.

printf '%s' "$oldname"

La commande printf est à utiliser de préférence à la commande echo car la première permet l’utilisation de n’importe quelle chaîne contrairement à la seconde. De plus, elle ne nécessite pas d’option particulière pour empêcher la génération automatique d’un retour à la ligne.

iconv -f utf-8 -t ascii//TRANSLIT

La commande iconv convertit une chaîne encodée UTF-8 (-f utf-8 en une chaîne encodée ASCII (-t ascii//TRANSLIT).

L’option //TRANSLISTdemande à iconv de faire de la translittération :

sed

La commande sed utilise plusieurs expressions rationnelles pour nettoyer la chaîne de caractères générée par iconv. Cette particularité permet de réduire le nombre de tubes utilisées contrairement à ce que des commandes tr auraient obligé.

Dans le détail, ces expressions sont :

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
transforme les majuscules en minuscules
s/[^a-z]+/-/g
transforme tout ce qui n’est pas lettre de l’alphabet en tirets (-)
s/-+/-/g
réduit les suites de tirets (-) en un seul tiret
s/^-//
supprime un éventuel tiret en début de chaîne
s/-$//
supprime un éventuel tiret en fin de chaîne

Code source

shell
newname=$(printf '%s' "$oldname" | \
    iconv -f utf-8 -t ascii//TRANSLIT | \
    sed -r -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' \
           -e 's/[^a-z]+/-/g' \
           -e 's/-+/-/g' \
           -e 's/^-//' \
           -e 's/-$//' \
)