2009-01-04 17 views
8

En bash se pueden escapar argumentos que contengan espacios en blanco.compilar listas de argumentos que contengan espacios en blanco

foo "a string" 

Esto también funciona para los argumentos de un comando o función:

bar() { 
    foo "[email protected]" 
} 

bar "a string" 

Hasta aquí todo bien, pero lo que si quiero manipular los argumentos antes de llamar foo?

Esto no funciona:

bar() { 
    for arg in "[email protected]" 
    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 

Entonces, ¿cómo construir listas de argumentos cuando los argumentos contienen espacios en blanco?

Respuesta

13

Hay (al menos) dos maneras de hacer esto:

(1.) utilizar una matriz y expandirlo utilizando "${array[@]}":

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

    foo "${args[@]}" 
} 

Entonces, ¿qué hemos aprendido? "${array[@]}" a ${array[*]} que "[email protected]" a $*.

(2.) O si no desea utilizar matrices es necesario utilizar eval:

bar() { 
    local args=() 
    for arg in "[email protected]" 
    do 
     args="$args \"prefix $arg\"" 
    done 

    eval foo $args 
} 
+0

maldición, debería haber llegado antes, podría haberte ahorrado el trabajo :) – hop

2

Use arrays (uno de los hidden features en Bash).

+1

cómo exactamente? He actualizado mi pregunta con un intento de usar una matriz, que no funcionó. – tarsius

+0

No parece haber una manera fácil de pasar matrices a funciones (que realmente son subcapas). Tendría que citarlos y pasarlos como argumento normal (como lo haría con cualquier otro comando). – JesperE

0

Puede utilizar las matrices al igual que usted sugiere, con un pequeño detalle cambiado. La línea que llama a foo debería leer

foo "${args[@]}" 
0

Tuve un problema con esto también. Estaba escribiendo un script bash para hacer una copia de seguridad de los archivos importantes en mi computadora con Windows (cygwin). Probé el enfoque de matriz también, y todavía tenía algunos problemas. No estoy seguro exactamente de cómo lo arreglé, pero aquí están las partes de mi código que son importantes en caso de que lo ayude.

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 
3

Aquí es una versión más corta: (ejemplo de construcción argumentos a un comando find)

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