Przekazywanie deklaracji funkcji w skrypcie Bash lub Shell?


96

Czy jest coś takiego bashlub przynajmniej coś podobnego (obejścia), jak deklaracje forward, dobrze znane na przykład w C / C ++?

Czy jest coś takiego, bo na przykład zawsze jest to wykonywane w jednym przebiegu (wiersz po wierszu)?

Jeśli nie ma deklaracji forward, co powinienem zrobić, aby mój skrypt był bardziej czytelny. Jest dość długi i te definicje funkcji na początku, zmieszane ze zmiennymi globalnymi, sprawiają, że mój skrypt wygląda brzydko i jest trudny do odczytania / zrozumienia)? Proszę o zapoznanie się z dobrze znanymi / najlepszymi praktykami w takich przypadkach.


Na przykład:

# something like forward declaration
function func

# execution of the function
func

# definition of func
function func
{
    echo 123
}

Odpowiedzi:


191

Świetne pytanie. Używam takiego wzorca dla większości moich skryptów:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

Możesz czytać kod od góry do dołu, ale w rzeczywistości nie rozpoczyna się on aż do ostatniej linii. Przekazując "$@"do main () można uzyskać dostęp do argumentów wiersza polecenia $1, $2i inni, tak jak zwykle.


3
Cześć, jak uporządkujesz dane, które mają być udostępniane między foo / bar / baz w twoim przykładzie? Zwykle po prostu umieszczam to na początku scenariusza. Czy tak jest nadal w przypadku korzystania z funkcji? A może lepiej jest umieścić dane globalne w main, a następnie przekazać je do foo / bar / baz jako argumenty? Jaka jest najlepsza praktyka?
— bodacydo

4
Wolę argumenty. Poza tym ustawię zmienne globalne mainw funkcji lub bezpośrednio po niej main(np. setupLub parseArguments). Unikam ustawiania zmiennych globalnych powyżej main- kod nie powinien wychodzić poza main.
— John Kugelman

Wydaje się to nieco analogiczne do tego, co if _ _ name _ _ == "_ _ main _ _": main()dzieje się w Pythonie
— Sergiy Kolodyazhnyy

Jest to również fantastyczne, gdy używasz narzędzi takich jak Bats do testowania skryptów, rozbicie wszystkiego na funkcje znacznie ułatwia testowanie poszczególnych komponentów. Zobacz także wpis na blogu
— dragon788

31

Kiedy moje skrypty bash za bardzo się rozrastają, używam mechanizmu dołączania:

Plik allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

Plik main:

#!/bin/bash

. allMyfunctions

foo
bar
baz

28
Osobiście, gdy skrypt powłoki zaczyna przekraczać jeden plik, mam tendencję do przełączania się na inny język ;-)
— Joachim Sauer

Czy nie byłoby lepiej użyć source allMyfunctions?
— pydoge

4
@pydoge: sourcenie jest zgodny z POSIX. bashdefiniuje sourcejako alias do .: są funkcjonalnie równoważne.
— mouviciel
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.