Pergunta

Em bash pode-se escapar argumentos que contenham espaços em branco.

foo "a string"

Isso também funciona para argumentos para um comando ou função:

bar() {
    foo "$@"
}

bar "a string"

Até aí tudo bem, mas o que se eu quiser manipular os argumentos antes de chamar foo?

Isso não funciona:

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

Assim como você construir listas de argumentos quando os argumentos conter espaços em branco?

Foi útil?

Solução

Há (pelo menos) duas maneiras de fazer isso:

  1. Use uma matriz e expandi-la utilizando "${array[@]}":

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

    Então, o que aprendemos? "${array[@]}" é ${array[*]} que "$@" é $*.

  2. Ou se você não quer matrizes de uso que você precisa para uso eval:

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

Outras dicas

Aqui está uma versão mais curta que não requer o uso de um índice numérico:

(exemplo: a construção de argumentos para um comando find)

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

Use matrizes (um dos hidden em Bash).

Você pode usar as matrizes apenas como você sugere, com um pequeno detalhe mudou. A linha que chama foo deve ler

 foo "${args[@]}"

Eu tive um problema com este demasiado bem. Eu estava escrevendo um script para fazer backup dos arquivos importantes no meu computador windows (cygwin). Eu tentei a abordagem variedade também, e ainda tinha algumas questões. Não tenho certeza exatamente como eu fixa-lo, mas aqui está as partes do meu código que são importantes no caso de ele irá ajudá-lo.

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top