Dlaczego muszę umieszczać „zrobić” w tym samym wierszu, co „za”?

28

1. Podsumowanie

Nie rozumiem, dlaczego potrzebuję reguły bashate E010 .


2. Szczegóły

Korzystam z bashate do segregowania.sh plików. Reguła E010:

zrobić nie na tej samej linii co do

for bashate:

  • Poprawny:

    #!/bin/bash
    for f in bash/*.sh; do
        sashacommand "$f"
    done
    
  • Błąd:

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

Czy jakieś ważne argumenty, dlaczego muszę fori dow tej samej linii?


3. Nieużyteczne

Nie mogę znaleźć odpowiedzi na moje pytanie w:

  1. Google
  2. Artykuły o najlepszych praktykach kodowania ( przykład )
  3. dokumentacja bashate . Znajduję tylko :

    Zestaw reguł, które pomagają zachować spójność w blokach kontrolnych. Są one ignorowane w długich liniach, które mają kontynuację, ponieważ rozwijanie jest swego rodzaju „interesujące”

Саша Черных
źródło
3
Wcięcie dojest zdecydowanie nieco nietypowe, ale for ... \ndo\n<indent>body...jest bardzo powszechne, a nawet bardziej to oceniłbym for ... ; do. Czy też na to narzeka?
Michael Homer
20
bashateto sprawdzanie stylu . Style są z natury subiektywne. Nie używaj go, jeśli nie podoba ci się styl biblioteki. Zamiast tego powinieneś rozważyć moduł sprawdzania składni / błędów, taki jak shellcheck .
Meuh
@meuh, dzięki, już korzystam z ShellCheck. moje pytanie: E010- tylko styl reguła lub w niektórych przypadkach muszę za i zrobienia w tej samej linii, nie tylko ze względów stylistycznych.
Саша Черных
10
Nigdy nie jest składniowym obowiązek posiadania przez i zrobić na tej samej linii w powłoce.
Meuh
1
@ Саша Черных To nie jest samo wcięcie, które jest niezwykłe, to wcięcie do. To jak wcięcia klamry Otwarcie ifi dodanie kodu na tej samej linii, jak w języku C. Kolejny przykład, jeśli pyton zezwolił, będzie kładzenie :od ifwcięty w następnej linii i dodanie kodu na tej samej linii. Sprawi, że będzie się to różnić dodatkowymi liniami w ciele.
JoL

Odpowiedzi:

60

Składniowo następujące dwa fragmenty kodu są poprawne i równoważne:

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

Ta ostatnia może ewentualnie być uznane trudniej rozumieć jako donieco zaciemnia polecenia w organizmie pętli. Jeśli pętla zawiera wiele poleceń, a następne polecenie znajduje się w nowym wierszu, zaciemnianie będzie dodatkowo podświetlone:

for f in *
    do cmd1
    cmd2
done

... ale oznaczenie go jako „błąd” jest osobistą opinią IMHO, a nie obiektywną prawdą.

Zasadniczo prawie każdy ;może zostać zastąpiony nowym wierszem. Zarówno ;i nowa linia są terminatorami poleceń. doto słowo kluczowe, które oznacza „tutaj następuje to, co należy zrobić (w tej forpętli)”.

for f in *; do ...; done

jest taki sam jak

for f in *
do
   ...
done

i jako

for f in *; do
   ...
done

Powodem do używania jednego nad drugim jest czytelność i konwencje w stylu lokalnym / osobistym.


Osobista opinia:

W nagłówkach pętli, które są bardzo długie , myślę, że warto umieścić donową linię, tak jak w

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

lub

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

To samo tyczy się thenw ifoświadczeniu.

Ale znowu sprowadza się to do osobistych preferencji stylowych lub dowolnego stylu kodowania stosowanego przez zespół / projekt.

Kusalananda
źródło
Mówisz: „W bardzo długich nagłówkach pętli sensowne może być wprowadzenie nowej linii”. Czy możesz podać przyczynę? Biorąc pod uwagę, że po nagłówku musi następować do, nie widzę powodu, dla którego umieszczenie go w następnym wierszu poprawiłoby jego czytelność.
Konrad Rudolph
3
@KonradRudolph Mój terminal ma szerokość 80 znaków. Jeśli lista zostanie zawinięta, utworzę z niej zestaw kontynuowanych linii (jak w moim ostatnim przykładzie), jeśli prawie się zawinie, umieszczę do(lub then) linię jako własną (jak w drugim do ostatniego przykładu). Wszystko to musi zależeć od osobistych preferencji. Nie lubię zbyt długich linii, częściowo dlatego, że mój terminal ma „tylko” 80 znaków szerokości, a częściowo dlatego, że uważam, że wygląda nieporządnie. Trudno mi też analizować bardzo długie linie pod kątem błędów.
Kusalananda
1
Nie ma potrzeby powtarzać, że jest to opinia. bashate jest przewodnikiem po stylu, więc z natury opiera się na opiniach.
Barmar
4
@Barmar, zwróć uwagę, że pytanie tutaj używa frazowania, takich jak „trzeba” i „rządzić”, a readme bashate nazywa dow oddzielnym wierszu „błąd”. Są to raczej surowe zwroty, więc nie wydaje się warto podkreślić, że wręcz przeciwnie, tak zwana „zasada” jest właściwie tylko subiektywna opinia.
ilkkachu
2
@mtraceur Racja, nie kwestionuję osobistych preferencji. Pamiętaj jednak, że cytowany limit czytelności nie dotyczy kodu. Dotyczy to tylko prozy. Ruch gałek ocznych zasadniczo różni się w przypadku odczytu kodu, więc dowody z tych badań nie mają tutaj zastosowania. A jeśli chodzi o wykorzystanie przyczyn historycznych, które nie mają już zastosowania jako uzasadnienie, cóż, użyliśmy również wcześniejszych nazw plików w wersji 8.3.
Konrad Rudolph
28

Zwróć uwagę na to, co jest napisane na górze strony:

bashate: odpowiednik pep8 dla skryptów bash

PEP8 to przewodnik po stylu dla kodu w języku Python. Podczas gdy ludzie Pythona często traktują swoje problemy ze stylem bardzo poważnie [potrzebne źródło] , to po prostu przewodnik. Możemy wymyślić zalety zarówno dla umieszczenia linii dow tej samej linii, jak fori dla umieszczenia jej w linii własnej.

To ta sama dyskusja, co do umieszczenia {kodu C podczas uruchamiania bloku iflub whilebloku (lub takiego).


Kilka wierszy poniżej w dokumentacji jest jeszcze jedna interesująca zasada:

E020: Deklaracja funkcji nie jest w formacie ^function name {$

Zakładam tutaj, że autor tego przewodnika po stylu uważa, że ​​użycie functionsłowa kluczowego jest konieczne, aby czytelnik mógł rozpoznać deklarację funkcji. Jednak function foojest niestandardowy sposób definiowania funkcji: standardowy sposób jest foo(). Jedyną różnicą między nimi (w Bash) jest to, że druga jest trudniejsza do przeniesienia do standardowej powłoki, jak /bin/shw Debianie lub Ubuntu.

Sugerowałbym więc wzięcie dowolnego przewodnika po stylu z odrobiną soli lub trzema i samodzielne wybranie najlepszego stylu. Dobry moduł sprawdzania stylu pozwala na wyłączenie niektórych testów (bashate musi bashate -i E010,E011zignorować te dwa testy). Doskonały moduł sprawdzania stylu pozwoliłby zmodyfikować testy, np. Aby sprawdzić przeciwieństwo E020 tutaj.

ilkkachu
źródło
12

TL; DR: Nie musisz. To tylko opinia jakiegoś kolesia.

Jak wiele innych, pisałem fortakie pętle od dziesięcioleci:

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

Ten układ podkreśla fakt, że do ... doneotaczają ciało pętli, takie jak nawiasy klamrowe w językach podobnych do C, i pozwalają nowym wierszom oddzielić elementy konstrukcji pętli.

Oczywiście toczą się wojny religijne na temat tego, gdzie należy założyć również nawiasy klamrowe, więc można powiedzieć, że jury wciąż nie bierze udziału w tej. IMHO, właśnie tak to miało działać; Bourne lubił dopasowane ograniczniki, por. if ... fi, case ... esaca potrzeba średnika w krótszej wersji ujawnia, że ​​jest on krótszy niż pierwotnie zaprojektowany. Nic w tym złego; postęp technologiczny i wiele rzeczy, które kiedyś wydawały się dobrym pomysłem, teraz są odrzucone goto. Ale dopóki cała społeczność skryptów nie przyjmie preferencji bashateautora (autorów), nie musisz nic robić.

Alexis
źródło
3
fiKtóry odpowiada if, i esacitd. Pochodzi z Algol 68. Jedynym powodem, dla którego forpętla „s donie jest zakończony przez odto, że odjest nazwą istniejącego standardowego narzędzia. Zobacz en.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix
Kusalananda
1
Właściwe i rozdzielone słowami kluczowymi bloki zostały również użyte w innych językach rodziny Algol, w tym w Pascal (który używa begin ... enditp.).
Alexis
2
Nie słyszałem o tej historii od, to zabawne ... (Chociaż dlaczego więc nie skończyć z for-loopami rof?)
Alexis
2
@alexis Cóż, jak powiedział Kusalananda, pochodzi z Algolu 68, to jest kluczowy punkt. Stephen Bourne, twórca oryginalnej powłoki Bourne'a, był pod silnym wpływem tego języka i dlatego trzymał się tej składni. Nawet kiedy pisał w C. Zobacz kod źródłowy powłoki bourne: minnie.tuhs.org//cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h Och, i przez sposób BEGINi ENDtam też są zdefiniowane.
Sergiy Kolodyazhnyy
1
Nawiasem mówiąc, cały ten styl formatowania również pochodzi z Algola 68. Jest FORi DObędzie również na oddzielnych liniach, zwyczajowo, z wyjątkiem, kiedy cała pętla będzie łatwo zmieścić się na jednej linii.
reinierpost
3

Dziwi mnie, że nikt jeszcze nie wspomniał o tej poprawnej i przenośnej składni:

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

Zauważ, że uważnie fori dosą na tej samej linii, bez średnikiem. Wynik:

alfa
bravo
charlie
Steven Penny
źródło
Popieram tę odpowiedź za umieszczenie wzmianki o tej niejasnej (ale w niektórych przypadkach krytycznej dla czystego i przenośnego kodu powłoki), ale warto wyraźnie wyjaśnić ludziom, że blokuje to parametry pozycyjne, a także czuję się zmuszony wspomnieć, że jedynym „prawdziwie przenośne (tm)” forma jest jedno gdzie for qi dosą na oddzielnych liniach (forma, w tym przykładzie był nieobsługiwane parę lat temu na oryginalnym Almquish shell ( ash): in-ulm.de/~mascheck/various/ bourne_args / # endnote )
mtraceur
Chociaż przykład w tej odpowiedzi działa dla mnie, zastosowanie go do przykładu w pytaniu OP nie działa.
Scribblemacher
3

Kilka dobrych odpowiedzi tutaj. Zawsze bierz przewodniki po stylu z odrobiną soli, a IMHO i doświadczeniem, bądź tak bardzo lekko lub umiarkowanie zaniepokojony każdą społecznością, która jest pełna nadmiernego dogmatu, jeśli chodzi o styl. To prawie tak, jakby wierzyli, że kiedy W KOŃCU dostaną ostatnią kropkę, i ostatnią literę T, to oprogramowanie będzie działać. Czasami usunięcie błędów wymaga więcej niż idealnego stylu ...

Kiedy zacząłem uczyć się powłoki, większość skryptów i tut używała wbudowanego formatu średnika

for i in "$@"; do
    stuff
done

ale ponieważ byłem niedoświadczony, miałem trochę trudności z zauważeniem; i do - oba niezbędne do potwierdzenia poprawności składniowej. Więc sam wolałem zrobić w następnym wierszu. Już tego nie robię (gra słów zamierzona)

Ponadto polecenie „while” jest doskonałym kandydatem na niezłą sztuczkę:

while prep1; prep2; condition; do
    stuff
done

ale gdy polecenia prep są nieco nieporęczne i / lub warunek jest złożony, lepiej go sformatować jako

while
    prep1
    prep2
    condition
do
    stuff
done

a następnie dołączenie do jako „; do” jest dodatnio niezrównane.

Możesz nawet stać się bardziej intensywny:

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

ponieważ każde zdanie jest wyrażeniem. Zwróć uwagę, jak oba style są używane oportunistycznie. Utrzymuj go w czystości i jest dość czytelny. Kompaktuj lub wykrzykuj w imię stylu lub „oszczędzania miejsca” i stanie się okropnym bałaganem.

Więc! Biorąc pod uwagę raczej barokowe style skryptów powłoki, wszystko, co ma na celu zwiększenie przejrzystości i łatwy wizualny dostęp do znaczących symboli, jest zawsze dobrą rzeczą.

Forma, w której „do” jest napisane w linii z poleceniem, jest słodka, gdy masz małe polecenie - nie uważam, że „do” jest ukryte wizualnie, ani też wewnętrzne polecenie nie jest naprawdę zasłonięte:

for i in whatever
  do stuff
done

Uważam, że jest to całkiem przyjemne i ma analogie z while, if i case:

while condition
  do stuff
end

if condition
  then stuff1
  else stuff2
fi

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

Codd * wymaga od ciebie jasności i ogólnego porządku.

* Edgar F. Codd, ojciec teorii relacyjnych baz danych.


źródło
1
Nigdy nie widziałem whileze ifstanu poprzedniego. Fajne!
Joe