Komentarze skryptu powłoki wielowierszowej - jak to działa?

92

Ostatnio natknąłem się na wieloliniowy typ komentarza, którego nigdy wcześniej nie widziałem - oto przykład skryptu:

echo a
#
: aaa 
: ddd 
#
echo b

To wydaje się działać, nawet vimpodkreśla składnię. Jak nazywa się ten styl komentowania i jak znaleźć więcej informacji na jego temat?

Wiesław Herr
źródło
1
Co, jeśli zamiast tego umieścisz kod w funkcji, aby go skomentować? CommentedOutBlock() { echo "test"; }
Buksy

Odpowiedzi:

135

To nie jest komentarz wieloliniowy. #to komentarz jednowierszowy. :(dwukropek) wcale nie jest komentarzem, ale raczej wbudowaną komendą powłoki, która jest w zasadzie NOP , operacją zerową, która nie robi nic oprócz powrotu true, jak true(a zatem ustawienie $?na 0 jako efekt uboczny). Ponieważ jednak jest to polecenie, może akceptować argumenty, a ponieważ ignoruje swoje argumenty, w większości przypadków powierzchownie działa jak komentarz. Głównym problemem związanym z tą kludge jest to, że argumenty są wciąż rozszerzane, co prowadzi do wielu niezamierzonych konsekwencji. Na argumenty nadal mają wpływ błędy składniowe, przekierowania są nadal wykonywane, więc : > filezostaną obcięte file, a : $(dangerous command)podstawienia nadal będą działać.

Najmniej zaskakujący całkowicie bezpieczny sposób wstawiania komentarzy w skryptach powłoki to #. Trzymaj się tego nawet w przypadku komentarzy wieloliniowych. Nigdy nie próbuj (ab) używać :do komentowania. Nie ma dedykowanego wieloliniowego mechanizmu komentowania w powłoce, który byłby analogiczny do postaci ukośnej gwiazdki /* */w Cpodobnych językach.


Ze względu na kompletność, ale nie dlatego, że jest to zalecana praktyka, wspomnę, że można użyć dokumentów tutaj do robienia wieloliniowych „komentarzy”:

: <<'end_long_comment'
This is an abuse of the null command ':' and the here-document syntax
to achieve a "multi-line comment".  According to the POSIX spec linked 
above, if any character in the delimiter word ("end_long_comment" in 
this case) above is quoted, the here-document will not be expanded in 
any way.  This is **critical**, as failing to quote the "end_long_comment" 
will result in the problems with unintended expansions described above. 
All of this text in this here-doc goes to the standard input of :, which 
does nothing with it, hence the effect is like a comment.  There is very 
little point to doing this besides throwing people off.  Just use '#'.
end_long_comment
jw013
źródło
29
+1 bardzo ważne, aby utrzymać pojedyncze cudzysłowy w <<linii - to wyłącza podstawianie i rozszerzanie.
glenn jackman
4
I jako dodatkowa uwaga, wypełnienie skryptów powłoki :elementami, które powinny być komentarzami, spowoduje dodatkowe zużycie pamięci RAM / procesora. Nie będzie to miało znaczenia dla prostych rzeczy na pulpicie, ale jeśli jest to wykonywane setki lub tysiące razy na sekundę, nic nie zrobisz, potężnie szybko .
bahamat
3
@bahamat: jeśli wykonasz coś setki lub tysiące razy na sekundę, mam nadzieję, że nie napiszesz tego w powłoce ... = /
7heo.tk
1
Czasami przydatne może być użycie narzędzia zerowego do wielu wierszy tekstu. Rozpoczęcie komentarza od : <<=cutumożliwia napisanie POD w skryptach powłoki, zobacz ten przykład, aby uzyskać szczegółowe informacje . Umożliwia to użycie perldoc script.sh. Jednak wieloliniowy komentarz pokazany w tej odpowiedzi powinien zdecydowanie być blokiem komentarza (każda linia zaczyna się od # ).
basic6
Oto miła dyskusja na temat heredoców, używanych zarówno do komentarzy, jak i innych interesujących przypadków użycia (nawet w tym do generowania skryptów dynaimc): tldp.org/LDP/abs/html/here-docs.html#EX71C
bguiz
28

To nie jest żaden styl komentowania. :wbudowaną komenda robi nic; jest nadużywane za komentowanie tutaj.

$ help :
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Ignacio Vazquez-Abrams
źródło
25

We wczesnych powłokach dwukropek był jedynym sposobem na tworzenie komentarzy.

Nie jest to jednak prawdziwy komentarz, ponieważ linia jest analizowana dokładnie w taki sam sposób, jak każde inne polecenie, co może mieć skutki uboczne. Na przykład:

: ${a:=x} # assigns the value 'x' to the variable, 'a'

: $(command) # executes 'command'

(Czasami okrężnica jest używana wyłącznie w celu wywołania tych skutków ubocznych, ale wtedy nie jest używana jako komentarz).

Czasami wygodnie jest użyć dwukropka, aby skomentować część skryptu:

: '
while [ "$n" -ne "$x" ]
do
  : whatever
done
'

Jest to wielka oszczędność czasu w porównaniu z poprzednimi wierszami #, szczególnie jeśli komentowanie jest tylko tymczasowe.

Chris FA Johnson
źródło
2
Ta metoda komentowania pojedynczych cudzysłowów nie działa na żadnej sekcji skryptu, która sama używa pojedynczych cudzysłowów. A jeśli używasz cudzysłowów w dowolnym miejscu tak blisko, jak powinieneś, oznacza to, że będziesz mieć uzasadnione pojedyncze cudzysłowy rozsypane w całym skrypcie. O wiele łatwiej jest po prostu użyć dowolnego porządnego edytora, który pozwala blokować komentarze w linii.
jw013,
Masz całkowitą rację, że zadziała to tylko wtedy, gdy w cytowanej sekcji nie będzie żadnych pojedynczych cudzysłowów. Jednak skrypt nie musi zawierać wielu pojedynczych cudzysłowów. Przeglądając kilka moich skryptów, stwierdzam, że są one stosunkowo rzadkie, a wiele z nich można zastąpić podwójnymi cudzysłowami.
Chris FA Johnson
Na wybór pojedynczego lub podwójnego cudzysłowu nie powinno mieć wpływu coś tak trywialnego i nieistotnego, jak to, czy tekst skryptu jest prawidłowym ciągiem pojedynczego cudzysłowu. Pojedyncze cudzysłowy służą do zapobiegania rozszerzeniom, a podwójne cudzysłowy pozwalają na niektóre rozwinięcia i wymagają dodatkowej analizy. To są prawdziwe kryteria określania, którego użyć.
jw013,
To zdecydowanie najmodniejszy sposób na zrobienie tego. Idealne dla małych bloków dokumentacji. Podoba mi się to lepiej /* */i nie zaczynaj <!-- -->!
alex grey
1

Jeśli Twój komentarz znajduje się na końcu skryptu, możesz to zrobić w następujący sposób:

#!/bin/sh
echo 'hello world'
exec true
we can put whatever we want here
\'\"\$\`!#%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
abcdefghijklmnopqrstuvwxyz{|}~
Steven Penny
źródło