Переслати декларації функцій у сценарії Bash або Shell?


95

Чи є bashщось подібне або, принаймні, щось подібне (обхід), як декларації пересилання, наприклад, добре відомі в C / C ++?

Або є така річ, тому що, наприклад, вона завжди виконується за один прохід (рядок за рядком)?

Якщо немає попередніх оголошень, що мені робити, щоб полегшити читання мого сценарію. Він досить довгий, і ці визначення функцій на початку, змішані з глобальними змінними, роблять мій сценарій вигляд негарним і важким для читання / розуміння)? Я прошу вивчити деякі відомі / найкращі практики для таких випадків.


Наприклад:

# something like forward declaration
function func

# execution of the function
func

# definition of func
function func
{
    echo 123
}

Відповіді:


190

Чудове запитання. Я використовую такий шаблон для більшості своїх сценаріїв:

#!/bin/bash

main() {
    foo
    bar
    baz
}

foo() {
}

bar() {
}

baz() {
}

main "$@"

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


3
Привіт, як ви структуруєте дані, якими має обмінюватися foo / bar / baz у вашому прикладі? Зазвичай я просто розміщую це у верхній частині сценарію. Чи все ще це відбувається при використанні функцій? Або краще вкласти глобальні дані в main, а потім передати їх до foo / bar / baz як аргументи? Яка найкраща практика?
бодацидо

4
Я віддаю перевагу аргументам. За винятком цього, я встановлю глобальні змінні в функції mainабо у функції відразу після main(наприклад, setupабо parseArguments). Я уникаю встановлення глобальних змінних вище main- код не повинен виходити за межі main.
Джон Кугельман

Це здається дещо аналогічним тому, що if _ _ name _ _ == "_ _ main _ _": main()робиться у python
Сергій Колодяжний

Це також фантастично, коли за допомогою таких інструментів, як Bats, випробовувати ваші сценарії, розбиття всього на функції полегшує тестування окремих компонентів. Дивіться також допис у блозі
dragon788

30

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

Файл allMyFunctions:

foo() {
}

bar() {
}

baz() {
}

Файл main:

#!/bin/bash

. allMyfunctions

foo
bar
baz

27
Особисто мені, коли сценарій оболонки починає зростати за одним файлом, я схильний переходити на іншу мову ;-)
Йоахім Зауер

Чи не краще було б використовувати source allMyfunctions?
pydoge

4
@pydoge: sourceне сумісний з POSIX. bashвизначає sourceяк псевдонім .: вони функціонально еквівалентні.
mouviciel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.