2015-05-06 14 views
5

Piszę skrypt bash, który przyjmuje niektóre opcjonalne parametry. Chcę je przetłumaczyć i przekazać do innego skryptu. Jednak trudno mi z wdziękiem przekazać opcjonalne parametry.Jak przekazać opcjonalne parametry do innego polecenia w skrypcie Bash?

Oto zarys tego, co udało mi się dostać pracę w Pseudokod:

a.sh:

if arg1 in arguments; then 
    firstArg="first argument" 
fi 
if arg2 in arguments; then 
    secondArg="second argument" 
fi 

./b.sh $firstArg $secondArg "default argument" 

Uwaga przestrzenie w argumentach.

b.sh:

for arg in "[email protected]" 
do 
    echo $arg 
done 

chcę zadzwonić b.sh, ewentualnie z firstArg i secondArg a domyślnym argumentem tak:

./b.sh $firstArg $secondArg "default argument" 

Problemem jest to, że jeśli $firstArg lub $secondArg są łańcuchami ze spacjami, będą one reprezentowane jako wiele argumentów, a wynik będzie podobny do:

first 
argument 
second 
argument 
default argument 

Dobra, to łatwo naprawić, niech przechwycić cały ciąg argumentów dodając cudzysłowy wokół niego tak:

./b.sh "$firstArg" "$secondArg" "defaultArg" 

Problem jest, jeśli, na przykład, firstArg nie jest ustawiona, to skutkuje pusty wiersz (jak to interpretować "" jako parametr), więc wyjście będzie coś takiego:

(blank line here) 
second argument 
defaultArg 

ja również próbował konstruowania ciąg i przekazaniem go do skryptu powłoki, ale nie robi wydaje się działać w ten sposób (int erprets cały ciąg jako argument, nawet jeśli dodaję oddzielne argumenty z cudzysłowami).

Pamiętaj, że wywoływanie b.sh z wiersza poleceń z cytowanymi argumentami działa poprawnie. Czy istnieje sposób naśladowania tego, jak działa to w skrypcie basha?

+1

marginesie: Tylko dlatego, że jestem kopiując swoje prowadzenie i używanie '.sh' rozszerzeń na plikach wykonywalnych (to znaczy plikach z uprawnieniami + x, wobec których wywołanie funkcji 'execv() 'się powiedzie) nie oznacza, że ​​jest to dobry pomysł. Ogólnie rzecz biorąc, polecenia w systemie UNIX nie powinny mieć żadnych rozszerzeń, bez względu na to, czy są dostarczane za pośrednictwem skryptu powłoki, skryptu Python, skompilowanego pliku binarnego itp. –

+0

Czy możesz wyraźnie wyjaśnić, czy jest to dla kodu używającego '#!/bin/sh' lub '#!/bin/bash'? –

+0

Używam bash. – Andrew

Odpowiedz

7

Jeżeli chcieliby, aby skopiować wszystkie argumenty podane, ale dodać jeszcze jedno:

# this works in any POSIX shell 
./b.sh "[email protected]" defaultArg 

Alternatywnie, jawnie przekazać firstArg i secondArg, ale tylko wtedy, gdy istnieje (zauważ, że set-to-an-pusty -wartość liczy się jako "istniejąca" tutaj):

# this works in any POSIX shell 
./b.sh ${firstArg+"$firstArg"} ${secondArg+"$secondArg"} defaultArg 

Jeśli chcesz traktować set-to-an-pustej wartości jako nie istniejące:

# this works in any POSIX shell 
./b.sh ${firstArg:+"$firstArg"} ${secondArg:+"$secondArg"} defaultArg 

Alternatywnym podejściem jest zbudować tablicę argumentów:

# this requires bash or another shell with arrays and append syntax 
# be sure any script using this starts with #!/bin/bash 
b_args=() 
[[ $firstArg ]] && b_args+=("$firstArg") 
[[ $secondArg ]] && b_args+=("$secondArg") 
b_args+=("default argument") 
./b.sh "${b_args[@]}" 

Jeśli chcesz coś z taką samą elastyczność jak metoda tablicy, ale bez problemów z kompatybilnością, zdefiniować funkcję; w nim, można bezpiecznie zastąpić "[email protected]" bez wpływu na resztę skryptu:

runB() { 
    set -- 
    [ -n "$firstArg" ] && set -- "[email protected]" "$firstArg" 
    [ -n "$secondArg" ] && set -- "[email protected]" "$secondArg" 
    ./b.sh "[email protected]" "default argument" 
} 
+0

Czy zacytowanie '" $ @ "' nie jest tutaj? Po tym czasie nie będzie już przedmiotem podziału na słowa ... prawda? – hek2mgl

+0

@ hek2mgl, co? Nie, podział słów jest tu wyraźnie niepożądany. –

+0

Dobra odpowiedź! Nie napisałem poprawnie tego pytania. – hek2mgl

1

używać tablicy:

args=() 

if [ ... ]; then 
    args+=("first argument") 
fi 

if [ ... ]; then 
    args+=("second argument") 
fi 

./b.sh "${args[@]}" "default argument" 
+0

@EtanReisner Nie, nie, ponieważ w przykładzie OP '$ firstArg' może nie być w ogóle ustawiony (ale użyty), ale jeśli zostanie ustawiony, zostanie ustawiony na literał łańcuchowy (tak samo w powyższym fragmencie). –

+0

Ach, założyłem, że były one zastępcze dla faktycznego pierwszego i drugiego argumentu, a nie literału (w OP, a także tutaj), a ponieważ pominąłeś faktyczne testy samych argumentów, nie wypełniłem ich. Jak napisałem to nie ma tego problemu, ale jak napisano, jest to tylko połowa rozwiązania (i myślę, że nie całkiem rozwiązuje to poprawnie). –

+0

Dostaję się tam, skąd pochodzisz. Jednak OP, który daje './b.sh" $ firstArg "" $ secondArg "" defaultArg "' jako możliwe rozwiązanie (i opisując jego jedyną wadę jako przechodzenie przez puste argumenty zamiast ich wcale nie dostarczać) wskazuje, że użycie literalnych ciągów "pierwszy argument" i "drugi argument" były po prostu niechlujstwem wcześniej w pytaniu. –

Powiązane problemy