37.3. Bash, version 4

La sortie de Bash version 4 a été annoncée le 20 février 2009, par Chet Ramey. Cette livraison comprenait un certain nombre de fonctionnalités notables ainsi que des corrections majeures.

Parmi les nouveautés :

37.3.1. Bash, version 4.1

La version 4.1 of Bash, publiée en mai 2010, était pour l'essentiel une mise à jour de correctifs.

  • La commande printf accepte maintenant l'option -v pour assigner les indexes des tableaux.

  • Entre les crochets doubles, les opérateurs de comparaison de chaînes de caractères > et < se conforment à présent à la locale. Étant donné que le réglage de la locale peut affecter l'ordre de tri des expressions littérales, il y a un risque d'effets de bord sur les tests de comparaison des expressions entre [[ ... ]].

  • La fonction intégrée read accepte maintenant l'option -N (read -N nb_car). Cette option provoque la sortie de read après nb_car caractères.

    Exemple 37.8. Lecture de N caractères

    #!/bin/bash
    # Nécessite Bash 4.1 au minimum
    
    nombre_de_caracteres=68
                                             # Lit les 75 premiers
    read -N $nombre_de_caracteres var < $0   # caractères du script
    echo "$var"
    exit
    
    ####### Sortie du script #######
    
    #!/bin/bash
    # Nécessite une version de Bash >= 4.1
    
    nombre_de_caracteres=68
    

  • A VERIF

    Here documents, intégrés dans une substitution de commande de la forme $( ... ), peuvent de terminer avec une simple ).

    Exemple 37.9. Utilisation d'un here document pour assigner une valeur à une variable

    #!/bin/bash
    # here-commsub.sh
    # Nécessite Bash 4.1 au minimum
    
    variable_multiligne=$( cat <<FINxxx
    ------------------------------
    Ceci est la ligne 1 de la variable
    Ceci est la ligne 2 de la variable
    Ceci est la ligne 3 de la variable
    ------------------------------
    FINxxx)
    
    #  Rather than what Bash 4.0 requires:
    #+ that the terminating limit string and
    #+ the terminating close-parenthesis be on separate lines.
    
    #  Ce qui est différent de la syntaxe de Bash 4.0,
    #+ qui exige que la chaîne marquant la fin de la
    #+ variable soit sur une ligne différente de
    #+ la parenthèse fermante.
    
    # FINxxx
    # )
    
    
    echo "$variable_multiligne"
    
    #  Bash affiche quand même un avertissement :
    #  avertissement : « here-document » à la ligne 12 délimité
    #+ par la fin du fichier (au lieu de « FINxxx »)
    
    

37.3.2. Bash, version 4.2

La version 4.2 of Bash, publiée en février 2011, contient un certain nombre de nouvelles fonctionnalités et d'améliorations, en plus des corrections de bugs.

  • Bash implémente à présent les échappements Unicode \u et \U.

    echo -e '\u2630'   
                                 # Caractère triple tiret horizontal empilé
    # Équivaut à la formulation détournée suivante :
    echo -e "\xE2\x98\xB0"
                       # Reconnue par les versions de Bash antérieures.
    
    echo -e '\u220F'   # Pi (lettre grecque et symbole mathématique)
    echo -e '\u0416'   # "Zhe" majuscule (caractère cyrillique)
    echo -e '\u2708'   # Symbole avion (police Dingbat)
    
    echo -e "Le circuit de cet amplificateur nécessite une résistance de tirage de 100 \u2126."  
    
    var_unicode='\u2640'
    echo -e $var_unicode      # Symbole féminin
    printf "$var_unicode \n"  # Symbole féminin avec retour à la ligne
    
    #  Et pour un cas un peu plus recherché...
    
    #  On peut stocker les symboles Unicode dans un tableau associatif
    #+ pour ensuite les retrouver par leur nom.
    #  Lancez cet exemple dans un terminal Gnome, ou un terminal muni
    #+ d'une police assez grosse et grasse pour la lisibilité.
    
    declare -A symbole  # Tableau associatif.
    
    symbole[script_E]='\u2130'
    symbole[script_F]='\u2131'
    symbole[script_J]='\u2110'
    symbole[script_M]='\u2133'
    symbole[Rx]='\u211E'
    symbole[TEL]='\u2121'
    symbole[FAX]='\u213B'
    symbole[care_of]='\u2105'
    symbole[account]='\u2100'
    symbole[trademark]='\u2122'
    
    
    echo -ne "${symbole[script_E]}   "
    echo -ne "${symbole[script_F]}   "
    echo -ne "${symbole[script_J]}   "
    echo -ne "${symbole[script_M]}   "
    echo -ne "${symbole[Rx]}   "
    echo -ne "${symbole[TEL]}   "
    echo -ne "${symbole[FAX]}   "
    echo -ne "${symbole[care_of]}   "
    echo -ne "${symbole[account]}   "
    echo -ne "${symbole[trademark]}   "
    echo
    
    [Note]

    Note

    L'exemple ci-dessus utilise la syntaxe de développement de chaînes $' ... '.

  • Lorsque l'option du shell lastpipe est mise, la dernière commande dans un pipe n'est pas exécutée dans un sous-shell.

    Exemple 37.10. Envoyer (par pipe) un flux d'entrée vers read

    #!/bin/bash
    # lastpipe-option.sh
    
    ligne=''                      # Null value.
    echo "\$ligne = « $ligne »"   # $ligne =
    
    echo
    
    shopt -s lastpipe         # Erreur avant la version 4.2
    echo "Code de retour du passage à 1 de l'option « lastpipe » : $?"
    #     1 pour les Bash avant 4.2, 0 dans le cas contraire.
    
    echo
    
                               # Envoie, via un tube, la première ligne du
    head -1 $0 | read ligne    # script à read.
    #            ^^^^^^^^^^      Pas dans un sous-shell.
    
    echo "\$ligne = « $ligne »"
    # Anciennes versions de Bash    $ligne = «  »
    # Bash version 4.2              $ligne = « #!/bin/bash »
    

    Cette option apporte éventuellement des « correctifs » pour ces scripts d'exemple : Exemple 34.3, « Envoyer la sortie de echo dans un tube pour un read » et Exemple 15.8, « Problèmes lors de la lecture d'un tube ».

  • Les indices de tableau négatifs permettent le décompte à l'envers, depuis la fin d'un tableau.

    Exemple 37.11. Indices de tableau négatifs

    #!/bin/bash
    # neg-array.sh
    # Nécessite Bash 4.2 au minimum
    
    
    tableau=( zero un deux trois quatre cinq )  # Tableau de 6 éléments.
    #         0    1   2    3    4    5
    #        -6   -5  -4   -3   -2   -1
    
    # Il est maintenant possible d'utiliser des indices négatifs.
    echo ${tableau[-1]}   # cinq
    echo ${tableau[-2]}   # quatre
    # ...
    echo ${tableau[-6]}   # zero
    # Les indices négatifs sont comptés à rebours à partir du
    # dernier élément+1
    
    # Mais vous ne pouvez pas utiliser d'indice au-delà du
    # premier élément du tableau.
    echo ${tableau[-7]}   # tableau: mauvais indice de tableau
    
    
    # Alors, à quoi sert cette nouvelle fonctionnalité ?
    
    echo "Le dernier élément du tableau est « ${tableau[-1]} »"
    # Ce qui est plus simple que :
    echo "Le dernier élément du tableau est « ${tableau[${#tableau[*]}-1]} »"
    echo
    
    # Et...
    
    indice=0
    let "dernier_indice_negatif = 0 - ${#tableau[*]}"
    # Nombre d'éléments, converti en nombre négatif.
    
    while [ $indice -gt $dernier_indice_negatif ]; do
      ((indice--)); echo -n "${tableau[indice]} "
    done  # Affiche les éléments du tableau, à l'envers.
          # Nous venons de simuler la commande « tac » avec ce
          # tableau.
    echo
    
    # Consultez également « neg-offset.sh ».
    

  • L'extraction de sous-chaîne utilise un paramètre de longueur négative pour spécifier un intervalle depuis la fin de la chaîne cible.

    Exemple 37.12. Paramètre négatif dans une extraction de chaîne

    #!/bin/bash
    # Bash, version 4.2 au minimum
    # Utilisation d'indices négatifs dans l'extraction de sous-chaînes.
    # Attention : cela change l'interprétation de cette structure.
    
    chaineZ=abcABC123ABCabc
    
    echo ${chaineZ}                              # abcABC123ABCabc
    #                Position dans la chaine :     0123456789.....
    echo ${chaineZ:2:3}                          #   cAB
    #  Sautez 2 caractères à partir du début de la chaîne, et
    #+ extrayez-en les 3 caractères suivant.
    #  ${chaîne:position:longeur}
    
    #  So far, nothing new, but now ...
    #  Jusqu'à présent, rien de neuf, mais maintenant...
    
                                                 # abcABC123ABCabc
    #                Position dans la chaine :     0123....6543210
    echo ${chaineZ:3:-6}                         #    ABC123
    #                ^
    #  Identifiez les indices situés 3 caractères après le début et
    #+ 6 caractères avant la fin et extrayez tous les caractères
    #+ entre les 2.
    #  ${chaîne:position-depuis-le-début:position-depuis-la-fin}
    #  Lorsque le paramètre « longueur » est négatif, il indique la
    #+ position à partir de la fin.
    
    #  Consultez également « neg-array.sh ».
    



[126] Plus particulièrement, Bash à partir de la version 4 comprend un support limité des tableaux associatifs. C'est une implémentation de base, à laquelle il manque la plupart des fonctionnalités des tableaux du même genre dans les autres langages de programmation.

[127] Copyright 1995-2009 by Chester Ramey.

[128] Ceci ne fonctionne qu'avec les tubes et quelques autres fichiers spéciaux.

[129] Mais seulement en association avec readline, c'est-à-dire depuis la ligne de commande.

[130] Et pendant que vous y êtes, pensez à remédier au problème bien connu du piped read.