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


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.