Пересылать объявления функций в сценарии Bash или Shell?

96

Есть ли такая вещь bashили, по крайней мере, что-то подобное (обходное решение), например, форвардные объявления, хорошо известные в C / C ++?

Или есть такая штука, потому что например она всегда выполняется за один проход (строка за строкой)?

Если нет форвардных объявлений, что мне делать, чтобы мой скрипт было легче читать. Он довольно длинный, и эти определения функций в начале, смешанные с глобальными переменными, делают мой скрипт некрасивым и трудным для чтения / понимания)? Я прошу ознакомиться с некоторыми хорошо известными / лучшими практиками для таких случаев.


Например:

# something like forward declaration
function func

# execution of the function
func

# definition of func
function func
{
    echo 123
}
Кирилл Киров
источник

Ответы:

191

Отличный вопрос. Я использую такой шаблон для большинства своих скриптов:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

Вы можете читать код сверху вниз, но на самом деле он не начинает выполняться до последней строки. Пропустив "$@"на магистральный () , вы можете получить доступ к аргументам командной строки $1, $2и др так же , как обычно.

Джон Кугельман
источник
3
Привет, как вы структурируете данные, которые должны быть разделены между foo / bar / baz в вашем примере? Обычно я просто помещаю его в начало сценария. Это все еще так при использовании функций? Или лучше поместить глобальные данные в main, а затем передать их в foo / bar / baz в качестве аргументов? Какая лучшая практика?
bodacydo 01
4
Я предпочитаю аргументы. Если этого не произойдет, я установлю глобальные переменные mainв функции сразу после main(например, setupили parseArguments). Я избегаю установки глобальных переменных выше main- код не должен выходить за пределы main.
Джон Кугельман 01
Это похоже на то, что if _ _ name _ _ == "_ _ main _ _": main()делает в python
Сергей Колодяжный
Это также замечательно при использовании таких инструментов, как Bats, для тестирования ваших скриптов, поскольку разбиение всего на функции значительно упрощает тестирование отдельных компонентов. См. Также сообщение в блоге
dragon788 09
31

Когда мои сценарии bash слишком разрастаются, я использую механизм включения:

Файл allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

Файл main:

#!/bin/bash

. allMyfunctions

foo
bar
baz
Mouviciel
источник
28
Лично я, когда сценарий оболочки начинает расти дальше одного файла, я склонен переключаться на другой язык ;-)
Joachim Sauer
Не лучше ли использовать source allMyfunctions?
pydoge
4
@pydoge: sourceне соответствует стандарту POSIX. bashопределяет sourceкак псевдоним .: они функционально эквивалентны.
mouviciel