Коментарі до сценарію багаторядкових оболонок - як це працює?


92

Нещодавно я натрапив на багаторядковий тип коментарів, якого я ніколи не бачив - ось приклад сценарію:

echo a
#
: aaa 
: ddd 
#
echo b

Це, здається, працює, навіть vimсинтаксис - це підкреслює. Як називається цей стиль коментування і як мені отримати більше інформації про нього?


1
Що робити, якщо замість цього загорнути свій код у функцію, щоб прокоментувати його? CommentedOutBlock() { echo "test"; }
Буксі

Відповіді:


135

Це не багаторядковий коментар. #- це коментар в одному рядку. :(двокрапка) - це зовсім не коментар, а скоріше вбудована команда оболонки, яка в основному є NOP , нульовою операцією, яка не робить нічого, крім повернення true, як true(і, таким чином, встановлюється $?0 як побічний ефект). Однак, оскільки це команда, вона може приймати аргументи, і оскільки вона ігнорує свої аргументи, в більшості випадків вона поверхово діє як коментар. Основна проблема цього хизу полягає в тому, що аргументи все ще розширюються, що призводить до безлічі непередбачуваних наслідків. На аргументи все ще впливають синтаксичні помилки, перенаправлення все ще виконуються, тому вони : > fileбудуть усіченими file, а : $(dangerous command)підстановки все ще будуть виконуватися.

Найменш дивно, абсолютно безпечний спосіб вставляти коментарі в сценарії оболонки - це #. Дотримуйтесь цього навіть для багаторядкових коментарів. Ніколи не намагайтеся (ab) використовувати :для коментарів. У оболонці немає виділеного багаторядкового механізму коментування, який би був аналогічним косої зірці /* */у Cмовах-подібних.


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

: <<'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

29
+1 Дуже важливо, щоб увімкнути єдині лапки <<- це вимикає заміну та розширення.
glenn jackman

4
І як додаткова примітка, заповнення скриптів оболонки :для речей, які слід коментувати, спричинить додаткове споживання оперативної пам'яті / процесора. Це не буде простим речами на вашому робочому столі, але якщо це щось виконується сотні чи тисячі разів в секунду, ви нічого не зробите , дуже швидко .
bahamat

3
@bahamat: якщо ви виконаєте щось сотні чи тисячі разів на секунду, я сподіваюся, що ви не
напишете

1
Іноді використання нульової утиліти для кількох рядків тексту може бути корисним. Починаючи з коментаря, : <<=cutможна писати POD у скриптах оболонки, детальніше див. Цей приклад . Це дає можливість використовувати perldoc script.sh. Однак багаторядковий коментар, показаний у цій відповіді, - це щось, що обов'язково повинно бути блоком коментарів (кожен рядок, починаючи з # ).
базовий6

Ось приємна дискусія про гередоки, які використовуються як для коментарів, так і для інших цікавих випадків використання (навіть включаючи генерацію сценарію dynaimc): tldp.org/LDP/abs/html/here-docs.html#EX71C
bguiz

28

Це не будь-який стиль коментування. :вбудована команда абсолютно нічого не робить; його тут зловживають за коментарі.

$ help :
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.

25

На ранніх оболонках товста кишка була єдиним способом створювати коментарі.

Однак це не справжній коментар, тому що рядок аналізується точно так само, як і будь-яка інша команда, яка аналізується, і це може мати побічні ефекти. Наприклад:

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

: $(command) # executes 'command'

(Іноді товсту кишку використовують виключно для того, щоб викликати ці побічні ефекти, але тоді вона не використовується як коментар.)

Іноді зручно використовувати двокрапку, щоб прокоментувати розділ сценарію:

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

Це чудовий час, що передує кожному рядку #, особливо якщо коментування є лише тимчасовим.


2
Цей метод коментування з однією цитатою не працює в жодному розділі сценарію, який сам використовує одинарні лапки. І якщо ви використовуєте цитати десь поблизу стільки, скільки вам слід, це означає, що у вас будуть легітимні одинарні цитати, розсипані всіма сценаріями. Настільки простіше просто використовувати будь-який гідний редактор, що дозволяє вам блокувати рядкові коментарі.
jw013

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

На вибір одинарної або подвійної цитати навряд чи слід впливати щось настільки тривіальне і не має ніякого занепокоєння, чи є сам текст вашого сценарію дійсним рядком з одним цитуванням. Одиничні лапки використовуються для запобігання розширень, тоді як подвійні лапки дозволяють певні розширення та потребують додаткового розбору. Це реальні критерії визначення того, який слід використовувати.
jw013

Це, безумовно, найчерезніший спосіб зробити це. Чудово підходить для маленьких блоків документації. Мені це подобається краще, ніж /* */і так, не запускайте мене <!-- -->!
alex grey

1

Якщо ваш коментар знаходиться в кінці сценарію, ви можете зробити це так:

#!/bin/sh
echo 'hello world'
exec true
we can put whatever we want here
\'\"\$\`!#%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
abcdefghijklmnopqrstuvwxyz{|}~
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.