Question

En bash, on peut échapper aux arguments contenant des espaces.

foo "a string"

Ceci fonctionne également pour les arguments d'une commande ou d'une fonction:

bar() {
    foo "$@"
}

bar "a string"

Jusqu'ici tout va bien, mais si je veux manipuler les arguments avant d'appeler toto ?

Cela ne fonctionne pas:

bar() {
    for arg in "$@"
    do
        args="$args \"prefix $arg\""
    done

    # Everything looks good ...
    echo $args

    # ... but it isn't.
    foo $args

    # foo "$args" would just be silly
}

bar a b c

Comment construit-on des listes d'arguments lorsque les arguments contiennent des espaces?

Était-ce utile?

La solution

Il existe (au moins) deux façons de procéder:

  1. Utilisez un tableau et développez-le à l'aide de " $ {array [@]} & <; code>:

    .
    bar() {
        local i=0 args=()
        for arg in "$@"
        do
            args[$i]="prefix $arg"
            ((++i))
        done
    
        foo "${args[@]}"
    }
    

    Alors, qu'avons-nous appris? "$ {array [@]}" est destiné à $ {array [*]} ce que "quot @" est à $ * .

  2. Si vous ne souhaitez pas utiliser de tableaux, vous devez utiliser eval :

    bar() {
        local args=()
        for arg in "$@"
        do
            args="$args \"prefix $arg\""
        done
    
        eval foo $args
    }
    

Autres conseils

Voici une version plus courte ne nécessitant pas l'utilisation d'un index numérique:

(exemple: construction d'arguments pour une commande find )

dir=$1
shift
for f in "$@" ; do
    args+=(-iname "*$f*")
done
find "$dir" "${args[@]}"

Utilisez les tableaux (l'un des fonctionnalités cachées dans Bash).

Vous pouvez utiliser les tableaux comme vous le suggérez, avec un petit détail modifié. La ligne appelant truc doit lire

 foo "${args[@]}"

J'ai aussi eu un problème avec cela. J'écrivais un script bash pour sauvegarder les fichiers importants sur mon ordinateur Windows (cygwin). J'ai aussi essayé la méthode des tableaux et j'ai encore quelques problèmes. Vous ne savez pas exactement comment j'ai résolu le problème, mais voici les parties de mon code qui sont importantes au cas où cela vous aiderait.

WORK="d:\Work Documents\*"
#   prompt and 7zip each file
for x in $SVN $WEB1 $WEB2 "$WORK" $GRAPHICS $W_SQL
do
    echo "Add $x to archive? (y/n)"
    read DO
    if [ "$DO" == "y" ]; then
        echo "compressing $x"
        7zip a $W_OUTPUT "$x"
    fi
    echo ""
done
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top