Навіщо писати весь сценарій bash у функціях?


59

На роботі я часто пишу баш сценарії. Мій керівник запропонував розбити весь сценарій на функції, подібно до наступного прикладу:

#!/bin/bash

# Configure variables
declare_variables() {
    noun=geese
    count=three
}

# Announce something
i_am_foo() {
    echo "I am foo"
    sleep 0.5
    echo "hear me roar!"
}

# Tell a joke
walk_into_bar() {
    echo "So these ${count} ${noun} walk into a bar..."
}

# Emulate a pendulum clock for a bit
do_baz() {
    for i in {1..6}; do
        expr $i % 2 >/dev/null && echo "tick" || echo "tock"
        sleep 1
    done
}

# Establish run order
main() {
    declare_variables
    i_am_foo
    walk_into_bar
    do_baz
}

main

Чи є якась причина для цього, крім "читабельності", що, на мою думку, могло б бути однаково добре встановленим ще кількома коментарями та деяким інтервалом між рядками?

Чи робить це сценарій більш ефективним (я б насправді очікував протилежне, якщо що-небудь), чи полегшує зміну коду, що перевищує вищезгаданий потенціал читання? Або це насправді лише стилістичні уподобання?

Зауважте, що хоч сценарій не демонструє це добре, порядок виконання функцій у наших фактичних сценаріях, як правило, дуже лінійний - walk_into_barзалежить від того, що i_am_fooбуло зроблено, і do_bazдіє на речі, створені walk_into_bar- таким чином ми можемо довільно поміняти порядок виконання - це не те, що ми зазвичай робимо. Наприклад, ви не раптом хотіли б поставити declare_variablesза собою walk_into_bar, що порушило б справи.

Прикладом того, як я написав би описаний вище сценарій, був би:

#!/bin/bash

# Configure variables
noun=geese
count=three

# Announce something
echo "I am foo"
sleep 0.5
echo "hear me roar!"

# Tell a joke
echo "So these ${count} ${noun} walk into a bar..."

# Emulate a pendulum clock for a bit
for i in {1..6}; do
    expr $i % 2 >/dev/null && echo "tick" || echo "tock"
    sleep 1
done

30
Мені подобається твій начальник. У своїх сценаріях я також ставлю main()вгорі і додаю main "$@"внизу, щоб викликати це. Це дозволяє спочатку побачити логіку сценарію високого рівня, коли ви відкриваєте її.
Джон Кугельман

22
Я не погоджуюся з думкою про те, що читабельність "може бути однаково добре встановлена ​​ще кількома коментарями та деяким інтервалом між рядками". За винятком художньої літератури, я б не хотів мати справу з книгою, яка не має змісту та описових назв для кожної глави та розділу. У мовах програмування це така читабельність, яку можуть надати функції, а коментарі не можуть.
Римоїд

6
Зверніть увагу , що змінні , оголошені в функції повинні бути оголошено local- це забезпечує змінний обсяг , який є неймовірно важливим в будь-якому нетривіальною сценарії.
Борис Павук

8
Я не згоден з вашим начальником. Якщо вам доведеться розбити сценарій на функції, ви, ймовірно, не повинні писати сценарій оболонки в першу чергу. Напишіть програму замість цього.
el.pescado

6
Функції призначені для процесів, які повторюються, або в межах сценарію, або в більш ніж одному сценарії. Вони також дозволяють запровадити єдині методології. Наприклад, використовуючи функцію для запису в syslog. Поки всі користуються однією і тією ж функцією, ваші записи в системі є більш послідовними. Функції одноразового використання, як ваш приклад, непотрібно ускладнюють сценарій. У деяких випадках вони вводять питання (змінне масштабування).
Xalorous

Відповіді:


39

Я почав використовувати цей самий стиль програмування bash, прочитавши повідомлення в блозі Кфіра Лаві "Defence Bash Programming" . Він дає досить багато вагомих причин, але особисто я вважаю це найважливішим:

  • процедури стають описовими: набагато простіше розібратися, що повинна робити певна частина коду. Замість стінки коду ви бачите "О, find_log_errorsфункція читає цей файл журналу на помилки". Порівняйте це з пошуком цілого ряду рядків awk / grep / sed, які використовують бог, знає, який тип регулярного виразів посеред тривалого сценарію - ви навіть не знаєте, що він там робить, якщо немає коментарів.

  • ви можете налагоджувати функції, додаючи в set -xта set +x. Коли ви знаєте, що решта коду працює добре, ви можете використовувати цей трюк, щоб зосередитись на налагодженні лише цієї конкретної функції. Звичайно, ви можете долучити частини сценарію, але що робити, якщо це довга частина? Простіше зробити щось подібне:

     set -x
     parse_process_list
     set +x
  • використання друку з cat <<- EOF . . . EOF. Я використовував його досить декілька разів, щоб зробити свій код набагато більш професійним. Крім того, parse_args()з getoptsфункцією досить зручно. Знову ж таки, це допомагає з легкістю для читання, замість того, щоб засунути все в сценарій як гігантську стінку тексту. Їх також зручно повторно використовувати.

І очевидно, що це набагато читабельніше для того, хто знає C чи Java, або Vala, але має обмежений досвід башма. Що стосується ефективності, то не так багато, що можна зробити - сам bash не є найбільш ефективною мовою, і люди віддають перевагу perl та python, коли справа стосується швидкості та ефективності. Однак ви можете niceфункціонувати:

nice -10 resource_hungry_function

У порівнянні з приємними дзвінками в кожному рядку коду, це зменшує весь набір тексту і може бути зручно використовувати, коли ви хочете, щоб лише частина вашого сценарію виконувалася з нижчим пріоритетом.

Запуск функцій у фоновому режимі, на мою думку, також допомагає, коли ви хочете, щоб у фоновому режимі була ціла купа операторів.

Деякі приклади, де я використовував цей стиль:


3
Я не впевнений, що ви повинні сприймати будь-які пропозиції з цієї статті дуже серйозно. Звичайно, у нього є кілька хороших ідей, але явно це не хтось звик до оболонок сценаріїв. Чи не єдиний параметр в будь-якому з прикладів котирується (!) , І він пропонує використовувати в верхньому регістрі імен змінних , які часто дуже погана ідея , тому що вони можуть вступати в протиріччя з існуючими окр вари. Ваші пункти у цій відповіді мають сенс, але пов'язану статтю, здається, написав хтось, хто просто звик до інших мов і намагається примусити свій стиль до баш.
terdon

1
@terdon Я повернувся до статті і перечитав її. Єдине місце, де автор згадує найменування змінних верхнього регістру, - у "Immutable Global Variables". Якщо ви розглядаєте глобальні змінні як ті, які повинні знаходитися в середовищі функції, то є сенс зробити їх капітальними. Зі сторони примітки, у посібнику bash не зазначено домовленості для змінних випадків. Навіть тут прийнята відповідь говорить "зазвичай", і єдиний "стандарт" - це Google, який не представляє всієї ІТ-галузі.
Сергій Колодяжний

@terdon щодо іншої ноти, я погоджуюсь на 100%, що цитування змінної повинно було бути зазначено в статті, і це було зазначено і в коментарях до блогу. Крім того, я б не судив когось, хто використовує цей стиль кодування, незалежно від того, використовується він чи ні іншою мовою. Ціле запитання та відповіді чітко показують, що в цьому є переваги, а ступінь людини, до якої вони звикли до іншої мови, тут, мабуть, не має значення.
Сергій Колодяжний

1
@terdon добре, стаття була розміщена як частина "вихідного" матеріалу. Я міг би опублікувати все як власну думку, але мені просто довелося визнати, що деякі речі я дізнався зі статті, і що все це з’явилося в результаті дослідження з часом. Авторська сторінка на зв’язку автора показує, що вони мають хороший досвід роботи з Linux та ІТ загалом, тому я думаю, що стаття насправді цього не показує, але я довіряю вашому досвіду, коли мова йде про сценарії Linux та оболонок, так що ви можете мати рацію .
Сергій Колодяжний

1
Це відмінна відповідь, але я також хотів би додати, що змінна область застосування в Bash є прикольною. З цієї причини я вважаю за краще оголосити свої змінні всередині функцій, використовуючи localі викликаючи все через main()функцію. Це робить речі набагато більш керованими, і ви можете уникнути потенційно безладної ситуації.
Гусні

65

Читання - це одне. Але в модуляризації є більше, ніж просто в цьому. ( Напівмодуляризація , можливо, правильніше для функцій.)

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

Ще один фактор функцій - повторне використання . Після того, як функція кодується, її можна застосувати кілька разів у сценарії. Ви також можете перенести його на інший сценарій.

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

Ще один момент, який потрібно додати. Як Etsitpab Nioliv зауважує у коментарі нижче, легко перенаправлятись із функцій як узгодженої сутності. Але є ще один аспект перенаправлення з функціями. А саме, перенаправлення можна встановити уздовж визначення функції. Напр .:

f () { echo something; } > log

Тепер явні перенаправлення не потрібні викликам функції.

$ f

Це може позбавити багатьох повторень, що знову підвищує надійність та допомагає підтримувати порядок.

Дивитися також


55
Дуже хороша відповідь, хоча було б набагато краще, якби вона була розбита на функції.
П'єр Арло

1
Можливо, додамо, що функції дозволяють імпортувати цей скрипт в інший сценарій (використовуючи sourceабо . scriptname.sh, і використовувати ці функції так, як якщо б вони були у вашому новому скрипті.
SnakeDoc

Про це вже йдеться в іншій відповіді.
Томаш

1
Я ціную це. Але я вважаю за краще, щоб і інші були важливими.
Томаш

7
Сьогодні я зіткнувся з випадком, коли мені довелося перенаправити частину виводу скрипту у файл (надіслати його електронною поштою) замість ехо. Мені просто довелося зробити myFunction >> myFile, щоб перенаправити висновок потрібних функцій. Досить зручно. Це може бути актуально.
Етсітпаб Ніолів

39

У своєму коментарі я згадав три переваги функцій:

  1. Їх простіше перевірити і перевірити правильність.

  2. Функції можна легко використати (отримати) у майбутніх сценаріях

  3. Ваш бос їх любить.

І, ніколи не варто недооцінювати важливість числа 3.

Я хотів би вирішити ще одне питання:

... так що ми можемо довільно поміняти порядок запуску - це не те, що ми зазвичай робимо. Наприклад, ви не раптом хотіли б поставити declare_variablesза собою walk_into_bar, що порушило б справи.

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

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


Я б заперечував, що іноді доцільно моделювати та застосовувати ці залежності, проти рефакторингу, щоб уникнути їх (оскільки якщо їх достатньо, і вони досить волохаті, це може просто призвести до випадку, коли речі вже не модулюються функції взагалі). Колись дуже складний випадок використання надихнув рамки зробити саме це .
Чарльз Даффі

4
Те, що потрібно розділити на функції, має бути, але приклад забирає це занадто далеко. Я думаю, що єдине, що мене справді клопоче, - це функція декларування змінної. Глобальні змінні, особливо статичні, повинні бути визначені глобально в коментованому розділі, присвяченому цій меті. Динамічні змінні повинні бути локальними для функцій, які їх використовують та змінюють.
Xalorous

@Xalorous Я бачив практику, коли глобальні змінні ініціалізуються в процедурі, як проміжний і швидкий крок до розробки процедури, яка зчитує їх значення із зовнішнього файлу ... Я погоджуюся, що слід чіткіше розділити визначення та ініціалізація, але рідко вам доведеться зігнути, щоб перейти до переваги №3;-)
Гастур

13

Ви розбиваєте код на функції з тієї ж причини, що і для C / C ++, python, perl, ruby ​​або будь-якого коду мови програмування. Більш глибокою причиною є абстракція - ви інкапсулюєте завдання нижчого рівня в примітиви (функції) вищого рівня, щоб вам не потрібно було турбуватися про те, як це робиться. У той же час код стає більш читабельним (і ремонтопридатним), а логіка програми стає більш чіткою.

Однак, дивлячись на ваш код, мені здається, що функція декларування змінних є досить дивною; це насправді змушує мене підняти око.


Занижена відповідь ІМХО. mainТоді ви пропонуєте оголосити змінні у функції / методі?
Девід Табернеро М.

12

Хоча я повністю погоджуюся з повторною використання , читабельністю і делікатним цілуванням начальників, але є ще одна перевага функцій : змінна область . Як показує LDP :

#!/bin/bash
# ex62.sh: Global and local variables inside a function.

func ()
{
  local loc_var=23       # Declared as local variable.
  echo                   # Uses the 'local' builtin.
  echo "\"loc_var\" in function = $loc_var"
  global_var=999         # Not declared as local.
                         # Therefore, defaults to global. 
  echo "\"global_var\" in function = $global_var"
}  

func

# Now, to see if local variable "loc_var" exists outside the function.

echo
echo "\"loc_var\" outside function = $loc_var"
                                      # $loc_var outside function = 
                                      # No, $loc_var not visible globally.
echo "\"global_var\" outside function = $global_var"
                                      # $global_var outside function = 999
                                      # $global_var is visible globally.
echo                      

exit 0
#  In contrast to C, a Bash variable declared inside a function
#+ is local ONLY if declared as such.

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

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


Мало хто явно використовує local, але я думаю, що більшість людей, що пишуть сценарії, розбиті на функції, все ще дотримуються принципу дизайну. Usign localпросто ускладнює введення помилок.
Voo

localробить змінні доступними для функціонування та її дітей, тому дуже приємно мати змінну, яку можна передати з функції A, але недоступну до функції B, яка може мати змінну з однаковою назвою, але з різною метою. Тож це добре для визначення сфери, і як сказав Voo - менше помилок
Сергій Колодяжний

10

Зовсім інша причина від тих, що вже вказані в інших відповідях: одна з причин, що ця методика іноді застосовується, коли єдиним висловленням про визначення функції на верхньому рівні є заклик до того main, щоб переконатися, що сценарій випадково не зробить нічого неприємного якщо сценарій усічений Сценарій може бути усічений, якщо він перенесений від процесу A до процесу B (оболонки), а процес A припиняється з будь-якої причини, перш ніж він закінчив писати весь сценарій. Особливо ймовірно, що це станеться, якщо процес A отримує сценарій з віддаленого ресурсу. Хоча з міркувань безпеки це не дуже гарна ідея, це щось робиться, і деякі сценарії були змінені, щоб передбачити проблему.


5
Цікаво! Але я вважаю занепокоєнням те, що треба дбати про ці речі в кожній з програм. З іншого боку, саме ця main()схема є звичайною в Python, де використовується if __name__ == '__main__': main()кінець файлу.
Мартін Удінг

1
Ідіома пітона має перевагу в тому, що інші сценарії не дозволяють importвиконувати поточний сценарій main. Я припускаю, що схожий охоронець може бути розміщений у баш-сценарії.
Джейк Кобб

@Jake Cobb Так. Я зараз роблю це у всіх нових сценаріях bash. У мене є скрипт, який містить основну інфраструктуру функцій, використовуваних усіма новими сценаріями. Цей сценарій можна отримати або виконати. Якщо джерело отримано, його основна функція не виконується. Виявлення джерела та виконання відбувається через те, що BASH_SOURCE містить ім'я виконавчого сценарію. Якщо він збігається з основним сценарієм, сценарій виконується. В іншому випадку його отримують джерела.
DocSalvager

7

Процес вимагає послідовності. Більшість завдань є послідовними. Немає сенсу возитися з наказом.

Але надзвичайно велика річ у програмуванні, що включає сценарії, - це тестування. Тестування, тестування, тестування. Які тестові сценарії у вас зараз мають підтвердити правильність своїх сценаріїв?

Ваш начальник намагається направити вас від того, щоб бути скриптом, щоб бути програмістом. Це хороший напрямок, щоб зайти. Люди, які прийдуть за вами, вам сподобаються.

АЛЕ Завжди пам’ятайте свої коріння, орієнтовані на процес. Якщо має сенс упорядкувати функції в тій послідовності, в якій вони зазвичай виконуються, то зробіть це, принаймні, як перший прохід.

Пізніше ви побачите, що деякі ваші функції обробляють введення, інші виводять, інші обробляють, інші моделюють дані та інші маніпулюють даними, тому може бути розумним групувати подібні методи, можливо, навіть переміщуючи їх в окремі файли .

Пізніше ви можете зрозуміти, що ви зараз написали бібліотеки невеликих допоміжних функцій, які використовуєте у багатьох своїх сценаріях.


6

Коментарі та інтервали не можуть дістатися ніде поблизу читабельності, яку можуть функціонувати, як я продемонструю. Без функцій ви не можете побачити ліс для дерев - великі проблеми ховаються серед багатьох рядків деталей. Іншими словами, люди не можуть одночасно зосередитися на тонких деталях та на великій картині. Це може бути не очевидним у короткому сценарії; доки він залишається коротким, він може бути достатньо читабельним. Програмне забезпечення стає більшим, хоча і не меншим, і, безумовно, воно є частиною всієї програмної системи вашої компанії, яка, безумовно, набагато більша, можливо, мільйони ліній.

Подумайте, чи я дав вам такі вказівки:

Place your hands on your desk.
Tense your arm muscles.
Extend your knee and hip joints.
Relax your arms.
Move your arms backwards.
Move your left leg backwards.
Move your right leg backwards.
(continue for 10,000 more lines)

До того часу, як ви пройшли на півдорозі, або навіть на 5%, ви б забули, що таке перші кілька кроків. Ви не могли помітити більшість проблем, тому що не могли бачити ліс для дерев. Порівняйте з функціями:

stand_up();
walk_to(break_room);
pour(coffee);
walk_to(office);

Це, безумовно, набагато зрозуміліше, незалежно від того, скільки коментарів ви могли б викласти в послідовної послідовної версії. Це також робить набагато більш ймовірним, що ви помітите, що ви забули приготувати каву, і, ймовірно, забули sit_down () наприкінці. Коли ваш розум продумує деталі греп-енд-регексів, ви не можете думати про велику картину - "а що, якщо кава не зроблена"?

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

Звичайно, є й інші переваги, які обговорюються в інших відповідях. Ще одна перевага, чітко не вказана в інших відповідях, полягає в тому, що функції забезпечують гарантію, яка важлива для запобігання та виправлення помилок. Якщо ви виявите, що якась змінна $ foo у правильній функції walk_to () була неправильною, ви знаєте, що вам потрібно лише подивитися на інші 6 рядків цієї функції, щоб знайти все, на що могла вплинути ця проблема, і все, що могло спричинили це неправильно. Без (належних) функцій все і все в цілій системі може бути причиною неправильного $ foo, і $ foo може впливати на все і все. Тому ви не можете безпечно виправити $ foo без повторного вивчення кожного рядка програми. Якщо $ foo є локальною для функції,


1
Це не bashсинтаксис. Прикро, хоча; Я не думаю, що існує спосіб передати вхід таким функціям. (тобто pour();< coffee). Це більше схоже на ( c++або phpя думаю).
голоси

2
@ tjt263 без дужок це синтаксис bash: налийте каву. Що стосується паренів, це майже всі інші мови. :)
Рей Морріс

5

Деякі відповідні вірші щодо програмування:

  • Ваша програма зміниться, навіть якщо ваш начальник наполягає, що це не так.
  • Тільки код і введення впливають на поведінку програми.
  • Називання складно.

Коментарі починаються як стоп-пробіл, оскільки ви не можете чітко висловити свої ідеї в коді *, а погіршуватися (або просто неправильно) із змінами. Тому, якщо це можливо, висловіть поняття, структури, міркування, семантику, потік, обробку помилок і все інше, що має відношення до розуміння коду як коду.

При цьому функції Bash мають деякі проблеми, які не зустрічаються в більшості мов:

  • Розміщення імен страшно в Bash. Наприклад, забувши використовувати localключове слово, це призводить до забруднення глобального простору імен.
  • Використання local foo="$(bar)"результатів втрачає вихідний кодbar .
  • Немає іменованих параметрів, тому ви повинні мати на увазі, що "$@"означає в різних контекстах.

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

** Використання коментарів для ліцензування, документації API тощо тощо все ще необхідно.


Я поставив майже всі локальні змінні, оголошуючи їх в нуль на початку функції ... local foo=""Тоді встановивши їх з допомогою виконання команд , щоб діяти на результат ... foo="$(bar)" || { echo "bar() failed"; return 1; }. Це швидко позбавляє нас від функції, коли необхідне значення не може бути встановлено. Фігурні брекети необхідні для того, щоб переконатися, що пристрій return 1виконується лише у випадку відмови.
DocSalvager

5

Час-гроші

Є й інші хороші відповіді, які поширюють світло на технічні причини, щоб написати модульно сценарій, потенційно довгий, розроблений в робочому середовищі, розроблений для використання групою осіб, а не лише для власного використання.

Хочу зосередитись на одному очікуванні: у робочому середовищі "час - це гроші" . Тож відсутність помилок та виконання вашого коду оцінюються разом із читальністю , тестабельністю , ремонтопридатністю , можливістю відновлення , повторною експлуатацією ...

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

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

Дотримання стандарту сповільнить вашу роботу на початку, але це прискорить роботу всіх інших (і ваших теж) згодом. Дійсно, коли співпраця зростає у кількості залучених людей, це стає неминучою потребою. Так, наприклад, навіть якщо я вважаю, що глобальні змінні мають бути визначені глобально, а не у функції, я можу зрозуміти стандарт, який ініціалізує їх у функції, що declare_variables()називається завжди в першому рядку main()одного ...

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

введіть тут опис зображення

Тут вище ви можете побачити, як розгортається лише walk_into_bar()функція. Навіть інші решта мали по 1000 рядків у кожному, ви все ще можете контролювати весь код на одній сторінці. Зауважте, що це складено навіть розділ, куди ви хочете оголосити / ініціалізувати змінні.


1

Крім причин, наведених в інших відповідях:

  1. Психологія: Програміст, продуктивність якого вимірюється в кодових рядках, буде стимулом писати зайвий багатослівний код. Чим більше керівництво фокусується на рядках коду, тим більше стимулів програмісту розширювати свій код із зайвою складністю. Це небажано, оскільки підвищена складність може призвести до збільшення витрат на обслуговування та збільшення зусиль, необхідних для виправлення помилок.

Це не така погана відповідь, як кажуть низовики. Примітка: agc каже, також це можливість, і так, це так. Він не каже, що це буде єдиною можливістю і нікого не звинувачує, лише констатує факти. Хоча я вважаю, що сьогодні майже не почута пряма контрактна робота у стилі «кодовий рядок» -> «$$», але непрямими засобами є звичайним явищем, що так, маса виробленого коду рахується лідерами / начальниками.
користувач259412

0

Ще одна причина, яку часто не помічають - це синтаксичний аналіз синтаксису bash:

set -eu

echo "this shouldn't run"
{
echo "this shouldn't run either"

Цей скрипт, очевидно, містить синтаксичну помилку, і bash не повинен запускати його взагалі, правда? Неправильно.

~ $ bash t1.sh
this shouldn't run
t1.sh: line 7: syntax error: unexpected end of file

Якби ми перетворили код у функцію, цього не сталося:

set -eu

main() {
  echo "this shouldn't run"
  {
  echo "this shouldn't run either"
}

main
~ $ bash t1.sh
t1.sh: line 10: syntax error: unexpected end of file
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.