Jak zmienić argument wiersza poleceń w Bash?


97

Czy istnieje sposób na zmianę argumentów wiersza poleceń w skrypcie Bash? Na przykład skrypt Bash jest wywoływany w następujący sposób:

./foo arg1 arg2  

Czy istnieje sposób na zmianę wartości arg1 w skrypcie? Coś jak:

$1="chintz"

Odpowiedzi:


153

Musisz zresetować wszystkie argumenty. Aby zmienić np $3:

$ set -- "${@:1:2}" "new" "${@:4}"

Zasadniczo ustawiasz wszystkie argumenty na ich bieżące wartości, z wyjątkiem tych, które chcesz zmienić. set --jest również określony w POSIX 7 .

"${@:1:2}"Notacja jest rozszerzony do dwóch (stąd 2w zapisie) argumenty pozycyjne począwszy od offsetu 1(tj $1). Jest to skrót dla "$1" "$2"w tym przypadku, ale jest dużo bardziej przydatne, gdy chcesz zastąpić np "${17}".


1
więc aby zmienić 3 dolary, muszę zmienić 1 dolara i 2 dolary, prawda? I zmienić je na co? Co oznacza „reset”?
Sriram

Dzięki za sztuczkę! Miałem trudności z używaniem tego do nazw plików z osadzonymi spacjami. Dla każdego, kto może napotkać ten problem, spróbuj umieścić evalna początku linii zgodnie z tym .
cxw

2
Jest to poprawne, jeśli znasz pozycję parametru, który chcesz zmienić. A jeśli tak naprawdę tego nie wiesz i musisz to dynamicznie zmieniać? Próbowałem z $ set - „$ {: 1: $ pivot}”, ale nie akceptuje tam zmiennej.
Daniele Segato

1
Jak mogę zrobić to samo z wnętrza funkcji? Twoje rozwiązanie nie działa, gdy jest wywoływane z wnętrza funkcji.
Hashken

3
Nie można zmienić parametrów pozycyjnych skryptu z poziomu funkcji - własne argumenty funkcji je ukrywają. Możesz jednak przechowywać je w tablicy i na tym operować.
thkala

23

Optymalizując pod kątem czytelności i łatwości konserwacji, możesz lepiej przypisać $1i $2do bardziej znaczących zmiennych (nie wiem, input_filename = $1i output_filename = $2czy coś), a następnie nadpisać jedną z tych zmiennych ( input_filename = 'chintz'), pozostawiając dane wejściowe dla skryptu niezmienione, na wypadek, gdyby tak było potrzebne gdzie indziej.


Chciałem podejścia, w którym mógłbym sam zmienić jeden z argumentów wejściowych. Musiałem to zrobić, ponieważ chciałem zwrócić wartość ze skryptu. Odpowiedź zasugerowana przez thkala zadziałała dobrze. Dzięki za odpowiedzi!!!
Sriram

3
@Johnsyweb Zgoda. Ze względu na czytelność Twoja jest lepszą metodą.
Dss

1
„Lepiej Ci będzie” zawsze zależy od przypadku użycia, którego nie podano.
Scott

2
@Scott 7 lat starszy i więcej doświadczenia niż ja, kiedy pisałem tę odpowiedź, jestem skłonny się z tobą zgodzić.
Johnsyweb,

Przykład, w którym to nie zadziała (poza użyciem czegoś takiego jak $ FIRST_PARAMETER): użycie i znaczenie parametru w zależności od rzeczywistej wartości.
Igor Stoppa

0

Wiem, że to stary, ale odpowiedź thkala okazała się bardzo pomocna, więc skorzystałem z pomysłu i nieco go rozwinąłem, aby umożliwić mi dodanie wartości domyślnych dla dowolnego argumentu, który nie został zdefiniowany - na przykład:


    # set defaults for the passed arguments (if any) if not defined.
    #
    arg1=${1:-"default-for-arg-1"}
    arg2=${2:-"default-for-arg-2"}
    set -- "${arg1}" "${arg2}"
    unset arg1 arg2

Mam nadzieję, że przyda się to komuś innemu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.