Какова цель команды, которая ничего не делает, будучи всего лишь лидером комментариев, но на самом деле является встроенной оболочкой?
Это медленнее, чем вставка комментария в ваши сценарии примерно на 40% за вызов, что, вероятно, сильно варьируется в зависимости от размера комментария. Единственные возможные причины, которые я вижу, это:
# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done
# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command
# an alias for `true' (lazy programming)
while : ; do command ; done
Я предполагаю, что я действительно ищу то, какое историческое применение это могло иметь.
Ответы:
Исторически сложилось , что у снарядов Борна не было
true
иfalse
встроенных команд.true
вместо этого был просто псевдоним:
, иfalse
что-то вродеlet 0
.:
немного лучше, чемtrue
для переносимости на древние раковины, полученные из Борна. В качестве простого примера рассмотрим отсутствие!
оператора конвейера или оператора||
списка (как это было в случае некоторых древних оболочек Борна). Это оставляетelse
предложениеif
оператора как единственное средство для ветвления на основе состояния выхода:Поскольку
if
требуется не пустоеthen
предложение, а комментарии не считаются непустыми, оно:
служит неактивным .В настоящее время (то есть: в современном контексте) вы обычно можете использовать либо
:
илиtrue
. Оба указываются в POSIX, и некоторые из нихtrue
легче читать. Однако есть одна интересная разница::
это так называемый POSIX специальный встроенные , аtrue
является обычным встроенным .Специальные встроенные элементы должны быть встроены в оболочку; Обычные встроенные функции только «типично» встроены, но это не гарантируется строго. Обычно не должно быть обычной программы, названной
:
с помощью функцииtrue
PATH в большинстве систем.Вероятно, самое важное отличие состоит в том, что со специальными встроенными модулями любая переменная, установленная встроенной функцией - даже в среде во время простой оценки команды - сохраняется после завершения команды, как показано здесь с использованием ksh93:
Обратите внимание, что Zsh игнорирует это требование, как и GNU Bash, за исключением случаев, когда он работает в режиме совместимости с POSIX, но все другие основные оболочки, производные от POSIX sh, соблюдают это, включая dash, ksh93 и mksh.
Другое отличие состоит в том, что обычные встроенные модули должны быть совместимы с
exec
- продемонстрировано здесь с использованием Bash:POSIX также явно отмечает, что это
:
может быть быстрее, чемtrue
, хотя, конечно, это детали реализации.источник
exec
?true
является обычным встроенным, но он неверен в том, чтоexec
использует/bin/true
вместо встроенного.: ${var?not initialized}
и др.:
что это специальная встроенная функция, которая не должна иметь названную им функцию. Но разве это не самый распространенный пример разветвленной бомбы,:(){ :|: & };:
называющей функцию именем:
?Я использую его, чтобы легко включить / отключить переменные команды:
таким образом
Это делает для чистого сценария. Это не может быть сделано с помощью «#».
Также,
это один из самых простых способов гарантировать, что «afile» существует, но имеет длину 0.
источник
>afile
еще проще и достигает того же эффекта.vecho=":"
? Просто для удобства чтения?Полезное приложение для: - если вы заинтересованы только в использовании расширений параметров для их побочных эффектов, а не в том, чтобы фактически передавать их результат команде. В этом случае вы используете PE в качестве аргумента либо:, либо false, в зависимости от того, хотите ли вы выйти из состояния 0 или 1. Примером может быть
: "${var:=$1}"
. Так:
как это встроенный, он должен быть довольно быстрым.источник
: $((a += 1))
(++
и--
операторы не должны быть реализованы в соответствии с POSIX.). В bash, ksh и других возможных оболочках вы можете сделать это:((a += 1))
или,((a++))
но это не указано в POSIX.(())
указывается как дополнительная функция. «Если последовательность символов, начинающаяся с« ((», будет проанализирована оболочкой как арифметическое расширение, если ей предшествует символ« $ », оболочки, которые реализуют расширение, посредством которого« ((выражение)) »оценивается как арифметическое выражение, можно обработать "((" как введение в качестве арифметической оценки вместо группирующей команды. ":
также может быть для комментария блока (аналогично / * * / на языке Си). Например, если вы хотите пропустить блок кода в вашем скрипте, вы можете сделать это:источник
\
избежать любого из символов разделителей для того же эффект:: <<\SKIP
.Если вы хотите обрезать файл до нуля байтов, что полезно для очистки журналов, попробуйте следующее:
источник
> file.log
проще и достигает того же эффекта.:>
более портативный. Некоторые оболочки (например, мояzsh
) автоматически создают экземпляр cat в текущей оболочке и прослушивают stdin при перенаправлении без команды. Скорееcat /dev/null
,:
намного проще. Часто это поведение отличается в интерактивных оболочках, а не в сценариях, но если вы пишете сценарий таким образом, что он также работает в интерактивном режиме, отладка методом копирования-вставки будет намного проще.: > file
отличаетсяtrue > file
(помимо количества персонажей и счастливого лица) в современной оболочке (при условии:
иtrue
одинаково быстро)?Это похоже на
pass
в Python.Одно из применений - заглушить функцию, пока она не будет написана:
источник
Еще два использования, не упомянутые в других ответах:
логирование
Взять этот пример скрипта:
Первая строка,
set -x
заставляет оболочку распечатать команду перед ее выполнением. Это довольно полезная конструкция. Недостатком является то, что обычныйecho Log message
тип заявления теперь печатает сообщение дважды. Метод двоеточия обходит это. Обратите внимание, что вам все равно придется экранировать специальные символы, как и дляecho
.Название работы Cron
Я видел, как это используется в работе cron, вот так:
Это задание cron, которое запускает скрипт
/opt/backup.sh
каждый день в 10:45. Преимущество этого метода заключается в том, что он лучше отображает темы электронной почты при/opt/backup.sh
выводе некоторого результата.источник
set -x
распечатанные команды (включая что-то вроде: foobar
) идут в stderr.Вы можете использовать его вместе с backticks (
``
) для выполнения команды без отображения ее вывода, например:Конечно, вы могли бы просто сделать
some_command > /dev/null
, но:
-версия несколько короче.При этом я бы не рекомендовал делать это на самом деле, потому что это могло бы просто сбить людей с толку. Это просто пришло на ум в качестве возможного варианта использования.
источник
Это также полезно для программ полиглот:
Это теперь и исполняемый скрипт оболочки и программа JavaScript: это означает
./filename.js
,sh filename.js
иnode filename.js
вся работа.(Определенно немного странное использование, но, тем не менее, эффективно.)
Некоторые объяснения, как и требовалось:
Shell-скрипты оцениваются построчно; и
exec
команда, когда выполняется, завершает оболочку и заменяет ее процесс результирующей командой. Это означает, что для оболочки программа выглядит так:Пока в слове не происходит расширения или псевдонима параметра, любое слово в сценарии оболочки может быть заключено в кавычки без изменения его значения; это означает, что
':'
это эквивалентно:
(мы только заключили это в кавычки здесь для достижения семантики JavaScript, описанной ниже)... и, как описано выше, первая команда в первой строке - это no-op (она переводит
: //
или, если вы предпочитаете заключать слова в кавычки,':' '//'
обратите внимание, что здесь//
нет особого значения, как в JavaScript; это просто бессмысленное слово, которое выбрасывают.)Наконец, вторая команда в первой строке (после точки с запятой) - это настоящая сущность программы: это
exec
вызов, который заменяет вызываемый shell-скрипт с процессом Node.js, вызываемым для оценки остальной части скрипта.Между тем, первая строка в JavaScript анализируется как string-literal (
':'
), а затем комментарий, который удаляется; Таким образом, для JavaScript программа выглядит так:Поскольку строковый литерал находится в строке сам по себе, он является оператором no-op и поэтому удаляется из программы; это означает, что вся строка удаляется, оставляя только ваш программный код (в данном примере,
function(){ ... }
тело.)источник
: //;
и~function(){}
делать? Спасибо:)
~function(){}
, это немного сложнее. Здесь есть пара других ответов, которые касаются этого, хотя ни один из них не объясняет это, к моему удовлетворению… если ни один из этих вопросов не объясняет это достаточно хорошо для вас, не стесняйтесь разместить его здесь как вопрос, я буду с удовольствием подробно расскажу о новом вопросе.node
. Так что функциональная часть - это все о javascript! Я в порядке с унарным оператором перед IIFE. Я думал, что это тоже bash, и на самом деле не совсем понял смысл вашего поста. Я в порядке, спасибо за ваше время, потраченное на добавление «разбивки»!~{ No problem. (= }
Самодокументируемые функции
Вы также можете использовать
:
для встраивания документации в функцию.Предположим, у вас есть библиотечный скрипт
mylib.sh
, предоставляющий множество функций. Вы можете либо получить библиотеку (. mylib.sh
) и вызывать функции непосредственно после этого (lib_function1 arg1 arg2
), либо избежать беспорядка в вашем пространстве имен и вызывать библиотеку с аргументом функции (mylib.sh lib_function1 arg1 arg2
).Не было бы неплохо, если бы вы могли также набирать
mylib.sh --help
и получать список доступных функций и их использование, без необходимости вручную поддерживать список функций в тексте справки?Несколько комментариев о коде:
declare -f
для перечисления всех доступных функций, а затем фильтрует их через sed, чтобы отображать только функции с соответствующим префиксом.mylib.sh function1
и он будет переведен внутриlib_function1
. Это упражнение оставлено читателю.$1
. В то же время, он будет загромождать ваше пространство имен, если вы создадите библиотеку. Если вам это не нравится, вы можете либо изменить имя на что-то похожее,lib_help
либо фактически проверить аргументы--help
в основном коде и вызвать функцию справки вручную.источник
Я видел это использование в скрипте и думал, что это хорошая замена для вызова базового имени в скрипте.
... это замена для кода:
basetool=$(basename $0)
источник
basetool=${0##*/}