2009-01-04 10 views
8

In Bash kann man Argumente entkommen, die Leerzeichen enthalten.Build-Argument-Listen mit Leerzeichen

foo "a string" 

Dies gilt auch für Argumente auf einen Befehl oder eine Funktion funktioniert:

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

bar "a string" 

So weit so gut, aber was ist, wenn ich vor dem Aufruf foo die Argumente manipulieren will?

funktioniert das nicht:

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 

Wie baut man Listen Argument, wenn die Argumente Leerzeichen enthalten?

Antwort

13

Es gibt (mindestens) zwei Möglichkeiten, dies zu tun:

(1.) ein Array verwenden und erweitern Sie es mit "${array[@]}":

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

    foo "${args[@]}" 
} 

Was haben wir gelernt? "${array[@]}" es zu ${array[*]} was "[email protected]" es zu $*.

(2.) Oder wenn Sie nicht Arrays wollen müssen Sie verwenden eval verwenden:

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

    eval foo $args 
} 
+0

Verdammt, hätte früher hier sein sollen - könnte dir die Arbeit erspart haben :) – hop

2

Verwenden Sie arrays (einer der hidden features in Bash).

+1

wie genau? Ich habe meine Frage mit einem Versuch aktualisiert, ein Array zu verwenden - das hat nicht funktioniert. – tarsius

+0

Es scheint keinen einfachen Weg zu geben, Arrays an Funktionen (die wirklich Subshells sind) zu übergeben. Sie müssen sie angeben und als reguläres Argument übergeben (wie bei jedem anderen Befehl). – JesperE

0

Sie können die Arrays verwenden, wie Sie vorschlagen, mit einem kleinen Detail verändert. Die Linie, die foo anruft, sollte

foo "${args[@]}" 
0

lesen Ich hatte ein Problem mit diesem auch. Ich schrieb ein Bash-Skript, um die wichtigen Dateien auf meinem Windows-Computer (Cygwin) zu sichern. Ich versuchte auch den Array-Ansatz und hatte immer noch einige Probleme. Ich bin mir nicht sicher, wie genau ich es repariert habe, aber hier sind die Teile meines Codes, die wichtig sind, falls es dir helfen wird.

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

Hier ist eine kürzere Version: (Beispiel Gebäude Argumente zu einem find Befehl)

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