Чому мені потрібно розміщувати "робити" в тому ж рядку, що і "за"?


28

1. Підсумок

Я не розумію, навіщо мені потрібне правило E010 про базовий екстракт .


2. Деталі

Я використовую басфат для зв'язування.sh файлів. Правило E010:

робити не на тій же лінії, що і для

for Базат:

  • Правильно:

    #!/bin/bash
    for f in bash/*.sh; do
        sashacommand "$f"
    done
    
  • Помилка:

    #!/bin/bash
    for f in bash/*.sh
        do sashacommand "$f"
    done
    

Чи є якісь вагомі аргументи, навіщо мені потрібні forі doв тому ж рядку?


3. Не корисний

Я не можу знайти відповідь на своє запитання в:

  1. Google
  2. Статті про найкращі практики кодування ( приклад )
  3. документація по басату . Я знаходжу лише :

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


3
Відступ do, безумовно, трохи незвичний, але for ... \ndo\n<indent>body...надзвичайно поширений, і я навіть вважаю, що більше for ... ; do. Чи теж скаржиться на це?
Майкл Гомер

20
bashate- це перевірка стилю . Стилі за своєю суттю суб'єктивні. Не використовуйте його, якщо вам не сподобається арбіотечний стиль, який він нав'язує. Натомість слід розглянути перевірку синтаксису / помилки, як оболонку .
meuh

@meuh, дякую, я вже використовую ShellCheck. моє запитання: E010- тільки стиль правило або в деяких випадках мені потрібно для і зробити в одній і тій же лінії , не тільки з причин стилю.
Саша Черних

10
Там ніколи не синтаксична обов'язок мати для і робити на ту ж рядок в оболонці.
meuh

1
@ Саша Черных Це не відступ сам по собі незвично, це відступ do. Це як відступи відкриває фігурної дужки ifі додати код на ту ж рядок в мові , як C. Іншого прикладу, якщо пітон дозволив це, було б поставивши :в ifабзаці на наступну рядку і додавання коду на ту ж рядок. Це призведе до того, що це відрізнятиметься додатковими лініями в кузові.
JoL

Відповіді:


60

Синтаксично наступні два фрагменти коду є правильними та еквівалентними:

for f in bash/*.sh; do
    sashacommand "$f"
done
for f in bash/*.sh
    do sashacommand "$f"
done

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

for f in *
    do cmd1
    cmd2
done

... але позначити це як "помилку" - це чиясь особиста думка ІМХО, а не об'єктивна правда.

Загалом, майже будь-який ;може бути замінений новим рядком. І ;новий рядок - це командні термінатори. do- це ключове слово, яке означає "тут випливає, що потрібно зробити (у цьому forциклі)".

for f in *; do ...; done

те саме, що

for f in *
do
   ...
done

і як

for f in *; do
   ...
done

Причина використовувати одне над іншим - читабельність та локальні / особисті умови стилів.


Особиста думка:

У заголовках циклу, які є дуже довгими , я думаю, що це може мати сенс розміщувати doновий рядок, як в

for i in animals people houses thoughts basketballs bees
do
    ...
done

або

for i in        \
    animals     \
    people      \
    houses      \
    thoughts    \
    basketballs \
    bees
do
    ...
done

Те саме стосується і thenу ifзаяві.

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


Ви кажете, що "У заголовках циклу, які є дуже довгими, можливо, має сенс перейти на новий рядок". Чи можете ви надати причину для цього? Зважаючи на те, що заголовок повинен дотримуватися do, я не бачу причини, чому його розміщення в наступному рядку допоможе читати.
Конрад Рудольф

3
@KonradRudolph Мій термінал має 80 символів. Якщо список обгортається, я зроблю його набором продовжених рядків (як у моєму останньому прикладі), якщо він майже завернеться, я поставлю do(або then) на рядок самостійно (як у другому до останнього прикладу). Це все стосується особистих уподобань. Мені не подобаються занадто довгі рядки, почасти тому, що мій термінал має "лише" 80 символів, а почасти тому, що я думаю, що це виглядає неохайно. Мені також важко розбирати дуже довгі рядки на помилки.
Кусалаланда

1
Здається, зайвим не вказувати, що це думка. Басат - це посібник зі стилів, тому він по суті заснований на думці.
Бармар

4
@Barmar, зауважте, що в цьому питанні використовуються фрази на зразок "потрібно" і "правило", а readmeta readmeta називає doокремий рядок "помилкою". Це досить суворі фрази, тому , мабуть, варто зазначити, що, навпаки, так зване «правило» насправді є лише суб’єктивною думкою.
ilkkachu

2
@mtraceur Правильно, я не сумніваюся в особистих уподобаннях. Але майте на увазі, що обмеження, яке ви цитуєте, не застосовується до коду. Це стосується лише прози. Рух очей принципово відрізняється для зчитування коду, тому докази цих досліджень тут не застосовуються. Що ж стосується використання історичних причин, які більше не застосовуються як обґрунтування, то ми також використовували минулі 8,3 імена файлів.
Конрад Рудольф

28

Зверніть увагу на те, що написано вгорі сторінки:

bashate: еквівалент pep8 для скриптів bash

PEP8 - посібник зі стилів для Python Code. У той час як люди Python часто здаються дуже серйозно сприймати свої стильові питання (потрібне цитування) , це саме те, керівництво. Ми можемо придумати переваги як для того, щоб поставити ту doсаму лінію, так forі для того, щоб поставити її на власну лінію.

Це те саме обговорення, як і куди поставити {код C при запуску ifабо whileблоку (або такого).


Кілька рядків нижче в документації є ще одне цікаве правило:

E020: Декларація функції не у форматі ^function name {$

Я припускаю, що справа в тому, що автор цього посібника зі стилів вважає, що використання functionключового слова необхідне, щоб читач розпізнавав декларацію функції. Однак function fooце нестандартний спосіб визначення функції: стандартний спосіб є foo(). Єдина відмінність між цими двома (у Bash) полягає в тому, що інший важче підключити до стандартної оболонки, як /bin/shу Debian або Ubuntu.

Отже, я б запропонував взяти будь-які подібні довідники стилів із зерном солі чи трьох та вирішити для себе, який найкращий стиль. Хороша перевірка стилів дозволяє відключити деякі перевірки (басфат bashate -i E010,E011повинен ігнорувати ці дві перевірки.) Прекрасна перевірка стилів дозволить вам змінити тести, наприклад, перевірити на протилежність E020 тут.


12

TL; DR: Вам цього не потрібно. Це просто якась думка думки.

Як і багато інших, я писав forподібні цикли протягом десятиліть:

for F in arg1 arg2 arg*
do
    somecommand "$F"
done

Цей макет підкреслює той факт, що do ... doneоточує тіло циклу, як фігурні дужки на мовах, подібних С, і дозволяє новим рядкам відокремлювати компоненти конструкції циклу.

Звичайно, існують релігійні війни щодо того, де також можна поставити фігурні дужки, тож ви можете сказати, що присяжних все ще немає. ІМХО, це явно, як це було розроблено для роботи; Борн захоплювався відповідними роздільниками, пор. if ... fi, case ... esacі потреба в крапці з комою в коротшій версії показує, що ви робите її коротшою, ніж спочатку розроблено. Нічого поганого в цьому; Прогрес технології та багато чого, що колись здавалося гарною ідеєю, зараз нахмуриться, як goto. Але поки вся громада сценаріїв оболонок не прийме уподобання bashateавтора (ів), вам нічого не потрібно робити.


3
Те, fiщо відповідає ifі esacт. Д., Походить від Algol 68. Єдина причина, по якій forцикл doне закінчується, od- odце ім'я існуючої стандартної утиліти. Дивіться en.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix
Kusalananda

1
Праві та блоки з обмеженими ключовими словами використовувались і в інших мовах сімейства Algol, включаючи Pascal (який використовує begin ... endі т.д.).
alexis

2
Ніколи не чув про цю історію od, це смішно ... (Хоча, чому б тоді просто не закінчити «петлі rof»)
alexis

2
@alexis Ну, як сказав Кусалаланда, він походить від Algol 68, ось ключовий момент. Стівен Борн, творець оригінальної оболонки Борна, зазнав сильного впливу цієї мови, і тому він дотримувався цього синтаксису. Навіть коли він писав у C. Див. Вихідний код для бурнової оболонки: minnie.tuhs.org//cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h О, і за спосіб, BEGINі ENDвони також визначені там.
Сергій Колодяжний

1
Весь цей стиль форматування, до речі, також походить від Algol 68. Його FORі DOбуде також по окремих лініях, за угодою, за винятком , коли весь цикл буде легко поміщається на одному рядку.
reinierpost

3

Я здивований, що ніхто не згадав про цей дійсний і портативний синтаксис:

set alfa bravo charlie
for q do
  echo "$q"
done

Зверніть увагу це forі doзнаходяться на одній лінії, без крапки з комою. Результат:

alfa
bravo
charlie

Я схвалюю цю відповідь, щоб підключити згадку про цей незрозумілий (але критичний для чистого та портативного коду оболонки в деяких випадках) синтаксис, однак варто чітко пояснити людям, що це клобує позиційні параметри, а також я змушений зазначити це Єдина "справді портативна (tm)" форма - це for qта, де і doзнаходяться в окремих рядках (форма в цьому прикладі була непідтримувана пару десятиліть тому на оригінальній оболонці Almquish ( ash): in-ulm.de/~mascheck/various/ bourne_args / # endnote )
mtraceur

Хоча приклад у цій відповіді працює для мене, застосувати його до прикладу у питанні ОП не працює.
Scribblemacher

3

Тут є кілька хороших відповідей. Завжди візьміть довідники стилів із зерном солі та ІМХО та досвідом, будьте завжди нехитрими до поміркованих занепокоєнь щодо будь-якої спільноти, яка наповнена зайвою догмою, коли справа стосується стилю. Це майже так, як вони вірять, що коли вони ОКОНЧЕНО отримають останню крапку, і останню T перекреслили, тоді програмне забезпечення буде працювати. Іноді для видалення помилок потрібен більш ніж ідеальний стиль ...

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

for i in "$@"; do
    stuff
done

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

Крім того, команда "while" є відмінним кандидатом на хороший маленький трюк:

while prep1; prep2; condition; do
    stuff
done

але коли команди попередньої підготовки трохи об'ємні, та / або умова є складною, її краще відформатувати як

while
    prep1
    prep2
    condition
do
    stuff
done

а потім додавання до документа як "; do" є позитивно нечітким.

Ви навіть можете отримати інтенсивніше, ніж це:

while
    if con1; then
      cond2
    elif cond3; then
      cond4
    elif cond5; then
      cond6
    else
      cond7
    fi
do
    stuff
done

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

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

Форма, де написано "робити", в рядку з командою, є солодкою, коли у вас є невелика команда - я не знаходжу "робити" візуально прихованим, і внутрішня команда не затьмарюється:

for i in whatever
  do stuff
done

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

while condition
  do stuff
end

if condition
  then stuff1
  else stuff2
fi

case $blah in
  a) stuff1;;
  b) stuff2;;
  c) stuff3;;
  *) stuffInfinity;;
esac

Чіткість та загальна охайність - це все, що Кодд * просить від вас.

* Едгар Ф. Кодд, батько теорії реляційних баз даних.


1
Ніколи раніше не бачив захворювання whileіз ifстаном. Класно!
Джо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.