Комментарии многострочного сценария оболочки - как это работает?

92

Недавно я наткнулся на многострочный тип комментария, которого я никогда раньше не видел - вот пример сценария:

echo a
#
: aaa 
: ddd 
#
echo b

Кажется, это работает, даже vimсинтаксис подчеркивает это. Как называется этот стиль комментирования и как найти больше информации об этом?

Веслав Герр
источник
1
Что если вместо этого вы закроете свой код в функцию, чтобы закомментировать его? CommentedOutBlock() { echo "test"; }
Буксы

Ответы:

135

Это не многострочный комментарий. #это однострочный комментарий. :(двоеточие) вовсе не комментарий, а встроенная команда оболочки, которая в основном представляет собой NOP , нулевая операция, которая ничего не делает, кроме возврата true, like 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
jw013
источник
29
+1 очень важно держать одинарные кавычки в <<строке - это отключает подстановку и расширение.
Гленн Джекман
4
И как дополнительное примечание, заполнение сценариев оболочки :для вещей, которые должны быть комментариями, приведет к дополнительному потреблению ОЗУ / ЦП. Это не будет иметь значения для простых вещей на вашем рабочем столе, но если это будет выполняться сотни или тысячи раз в секунду, вы ничего не сделаете , очень быстро .
Багамат
3
@bahamat: если вы выполняете что-то сотни или тысячи раз в секунду, я надеюсь, что вы не напишете это в оболочке ... = /
7heo.tk
1
Иногда полезно использовать нулевую утилиту для нескольких строк текста. Начиная комментарий с : <<=cutпозволяет писать POD в сценариях оболочки, подробности смотрите в этом примере . Это позволяет использовать perldoc script.sh. Однако многострочный комментарий, показанный в этом ответе, обязательно должен быть блоком комментариев (каждая строка начинается с # ).
basic6
Вот хорошее обсуждение heredocs, которое используется как для комментариев, так и для других интересных случаев использования (даже включая генерацию сценария 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
Это самый лучший способ сделать это. Отлично подходит для небольших блоков документации. Мне нравится это лучше чем /* */и тьфу, не заводите меня <!-- -->!
Алекс
1

Если ваш комментарий находится в конце скрипта, вы можете сделать это так:

#!/bin/sh
echo 'hello world'
exec true
we can put whatever we want here
\'\"\$\`!#%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
abcdefghijklmnopqrstuvwxyz{|}~
Стивен Пенни
источник