2009-08-06 7 views
0

Je regardais le script /etc/bash_completion trouvé dans certains paquets Debian. Je souhaitais utiliser le code qui parcourt un répertoire spécifique (/etc/bash_completion.d/ par défaut) et sources chaque fichier dans ce répertoire. Malheureusement, essayer d'exécuter le script provoque des erreurs sous la version Mac OS X de bash. Les lignes en question sont:Syntaxe de comparaison de chaînes Bash

for i in $BASH_COMPLETION_DIR/*; do 
    [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|.rpm*) ]] && 
    [ \(-f $i -o -h $i \) -a -r $i ] && . $i 
done 

Plus précisément, ma version de bash (3.2.17) étrangle la construction @(). Je comprends que le but de ce premier test est de s'assurer que nous ne recevons pas de fichiers d'échange ou de sauvegardes, etc. Je voudrais comprendre exactement ce que fait cette syntaxe, et, si possible, comment obtenir quelque chose de similaire (et même élégant) fonctionnant sur mon ancienne copie de bash. Quelqu'un peut-il offrir un aperçu?

Répondre

3

C'est simplement une extension de la comparaison de shell qui est équivalente à l'opérateur grep "ou" (|). Selon votre version bash, il se peut qu'il ne soit pas disponible ou que vous deviez définir extglob avec le shopt intégré. Voir la transcription de la session suivante:

 
    [email protected]> $ bash --version 
     GNU bash, version 3.2.48(21)-release (i686-pc-cygwin) 
     Copyright (C) 2007 Free Software Foundation, Inc. 
    [email protected]> echo @(*~|*.pl) 
     bash: syntax error near unexpected token '(' 
    [email protected]> shopt extglob 
     extglob off 
    [email protected]> shopt -s extglob 
    [email protected]> echo @(*~|*.pl) 
     qq.pl qq.sh~ xx.pl 
    [email protected]> 

qui permet ce qui suit au travail:

 
    ?(pattern-list) 
     Matches zero or one occurrence of the given patterns 
    *(pattern-list) 
     Matches zero or more occurrences of the given patterns 
    +(pattern-list) 
     Matches one or more occurrences of the given patterns 
    @(pattern-list) 
     Matches one of the given patterns 
    !(pattern-list) 
     Matches anything except one of the given patterns 

Si vous ne pouvez pas faire fonctionner avec shopt, vous pouvez générer un effet similaire avec des méthodes plus anciennes telles as:

 
    #!/bin/bash 
    for i in $BASH_COMPLETION_DIR/*; do 
     # Ignore VIM, backup, swp, files with all #'s and install package files. 
     # I think that's the right meaning for the '\#*\#' string. 
     # I don't know for sure what it's meant to match otherwise. 

     echo $i | egrep '~$|\.bak$|\.swp$|^#*#$|\.dpkg|\.rpm' >/dev/null 2>&1 
     if [[ $? == 0 ]] ; then 
      . $i 
     fi 
    done 

Alternativement, s'il y a plusieurs déterminations complexes qui décideront si vous voulez qu'il provienne , vous pouvez utiliser une variable doit initialement définie sur true et la définir sur false si l'une de ces conditions se déclenche. Par exemple, le qq.sh script suivant:

 
    #!/bin/bash 
    for i in * ; do 
     doit=1 

     # Ignore VIM backups. 
     echo $i | egrep '~$' >/dev/null 2>&1 
     if [[ $? -eq 0 ]] ; then 
      doit=0 
     fi 

     # Ignore Perl files. 
     echo $i | egrep '\.pl$' >/dev/null 2>&1 
     if [[ $? -eq 0 ]] ; then 
      doit=0 
     fi 

     if [[ ${doit} -eq 1 ]] ; then 
      echo Processing $i 
     else 
      echo Ignoring $i 
     fi 
    done 

a fait cela dans mon répertoire personnel:

 
    Processing Makefile 
    Processing binmath.c 
    : : : : : 
    Processing qq.in 
    Ignoring qq.pl --+ 
    Processing qq.sh | 
    Ignoring qq.sh~ --+--- see? 
    Processing qqin  | 
    : : : : :   | 
    Ignoring xx.pl --+ 
+1

pages pertinentes du manuel Bash: http://www.gnu.org/software/bash /manual/html_node/Pattern-Matching.html et http://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html –

+0

Merci Adam, je les cherchais. – Jim

+0

Excellent. La chose shopt a bien fonctionné! Merci pour les explications. –

Questions connexes