Какова цель: (двоеточие) GNU Bash builtin?
какова цель команды, которая ничего не делает, будучи немного больше, чем лидером комментариев, но на самом деле является встроенной оболочкой?
это медленнее, чем вставка комментария в ваши скрипты примерно на 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
Я думаю, что я действительно ищу, какое историческое приложение он мог бы иметь.
11 ответов:
исторически, у Борна снарядов не было
true
иfalse
как встроенные команды.true
вместо этого был просто псевдоним:
иfalse
что-то вродеlet 0
.
:
немного лучше, чемtrue
для переносимости на древние раковины Борна. В качестве простого примера рассмотрим отсутствие!
оператор конвейера, ни||
оператор списка (как это было в случае некоторых древних оболочек Борна). Это оставляетelse
пункт изif
оператор как единственное средство для ветвления на основе состояния выхода:if command; then :; else ...; fi
С
if
требуется непустойthen
предложения и комментарии не считаются непустыми,:
служит в качестве no-op.в наше время (то есть: в современном контексте) вы обычно можете использовать либо
:
илиtrue
. Оба указаны POSIX, а некоторые находятtrue
легче читать. Однако есть одно интересное отличие::
- это так называемый POSIX специальный встроенный, тогда какtrue
- это обычный причине-в.
специальные встроенные модули должны быть встроены в оболочку; обычные встроенные модули только "обычно" встроены, но это не гарантируется строго. Обычно не должно быть обычной программы с именем
:
С функциейtrue
в пути большинства систем.вероятно, самое важное различие заключается в том, что с специальные встроенные модули, любая переменная, установленная встроенным-даже в среде во время простой оценки команды - сохраняется после завершения команды, как показано здесь с помощью ksh93:
$ unset x; ( x=hi :; echo "$x" ) hi $ ( x=hi true; echo "$x" ) $
обратите внимание, что Zsh игнорирует это требование, как и GNU Bash, за исключением работы в режиме совместимости POSIX, но все другие основные оболочки "POSIX SH derived" соблюдают это, включая dash, ksh93 и mksh.
еще одно отличие заключается в том, что регулярные встроенные модули должен быть совместим с
exec
- продемонстрировано здесь с помощью Bash:$ ( exec : ) -bash: exec: :: not found $ ( exec true ) $
POSIX также явно отмечает, что
:
может быть быстрее, чемtrue
, хотя это, конечно, конкретная деталь реализации.
Я использую его, чтобы легко включить/отключить переменную команды:
#!/bin/bash if [[ "$VERBOSE" == "" || "$VERBOSE" == "0" ]]; then vecho=":" # no "verbose echo" else vecho=echo # enable "verbose echo" fi $vecho "Verbose echo is ON"
$ ./vecho $ VERBOSE=1 ./vecho Verbose echo is ON
Это чистый сценарий. Это не может быть сделано с '#'.
и
: >afile
является одним из самых простых способов гарантировать, что "afile" существует, но имеет длину 0.
полезное приложение для : Если вы заинтересованы только в использовании расширений параметров для их побочных эффектов, а не в фактической передаче их результата команде. В этом случае вы используете PE в качестве аргумента либо : либо false в зависимости от того, хотите ли вы получить статус выхода 0 или 1. Примером может быть
: "${var:=}"
. Так как:
это встроенный он должен быть довольно быстро.
:
также может быть для комментария блока (аналогично /* */ на языке C). Например, если вы хотите пропустить блок кода в своем скрипте, вы можете сделать это:: << 'SKIP' your code block here SKIP
Это похоже на
pass
в Python.одно использование было бы заглушить функцию, пока она не будет записана:
future_function () { :; }
Если вы хотите усечь файл до нуля байт, полезно для очистки журналов, попробуйте следующее:
:> file.log
вы можете использовать его в сочетании с обратные кавычки (
``
) для выполнения команды без отображения ее выходных данных, например:: `some_command`
конечно, вы могли бы просто сделать
some_command > /dev/null
, а:
-версия несколько короче.это, как говорится, я бы не рекомендовал на самом деле делать это, как это будет просто запутать людей. Это просто пришло на ум как возможный вариант использования.
еще два использования, не упомянутые в других ответах:
лесозаготовки
взять этот скрипт:
set -x : Logging message here example_command
первая строка
set -x
, заставляет оболочку распечатать команду перед ее запуском. Это довольно полезная конструкция. Недостатком является то, что обычныйecho Log message
тип оператора теперь печатает сообщение дважды. Метод двоеточия обходит это. Обратите внимание, что вам все равно придется избегать специальных символов, как и дляecho
.Cron названия должностей
Я видел, как он используется в заданиях cron, например:
45 10 * * * : Backup for database ; /opt/backup.sh
это задание cron, которое запускает скрипт
/opt/backup.sh
каждый день в 10:45. Преимущество этого метода заключается в том, что он делает для более красивых тем электронной почты, когда/opt/backup.sh
выводит некоторые выходные данные.
это также полезно для программ полиглот:
#!/usr/bin/env sh ':' //; exec "$(command -v node)" "" "$@" ~function(){ ... }
теперь это как исполняемый shell-script и программа JavaScript: значение
./filename.js
,sh filename.js
иnode filename.js
все работает.(определенно немного странное использование, но тем не менее эффективное.)
некоторые пояснения, как и просили:
Shell-скрипты оцениваются построчно; и при запуске, разрывает оболочку и заменяет это процесс с результирующей командой. Это означает, что для оболочки программа выглядит так:
#!/usr/bin/env sh ':' //; exec "$(command -v node)" "" "$@"
пока в слове не происходит расширения или сглаживания параметров,любой слово в оболочке-скрипте может быть заключено в кавычки без изменения его значения; это означает, что
':'
эквивалентно:
(мы только завернули его в кавычки здесь, чтобы достичь семантики JavaScript описано ниже)... и как описано выше, первая команда в первой строке-это no-op (это переводится как
: //
, или если вы предпочитаете цитировать слова,':' '//'
. Обратите внимание, что//
здесь нет особого смысла, как это происходит в JavaScript; это просто бессмысленное слово, которое выбрасывается.)наконец, вторая команда в первой строке (после точки с запятой) - это настоящее мясо программы: это
exec
вызов, который заменяет shell-скрипт вызывается, С узлом.процесс js вызывается для оценки остальное скрипта.между тем, первая строка в JavaScript анализируется как строковый литерал (
':'
), а затем комментарий, который удаляется; таким образом, в JavaScript, программа выглядит так:':' ~function(){ ... }
поскольку строковый литерал находится в строке сам по себе, он является оператором no-op и, таким образом, лишен программы; это означает, что вся строка удаляется, оставляя только ваш программный код (в данном примере
function(){ ... }
тело.)
самодокументируемыми функции
вы также можете использовать
:
для внедрения документации в функцию.Предположим, у вас есть библиотека script
mylib.sh
, обеспечивая разнообразие функции. Вы можете либо источник библиотеки (. mylib.sh
) и вызов функции непосредственно после этого (lib_function1 arg1 arg2
), или избежать загромождения пространства имен и вызвать библиотеку с аргументом функции (mylib.sh lib_function1 arg1 arg2
).было бы неплохо, если бы вы также могли ввести
mylib.sh --help
и получаем список доступных функций и их использование, без необходимости вручную поддерживать список функций в тексте справки?#!/bin/bash # all "public" functions must start with this prefix LIB_PREFIX='lib_' # "public" library functions lib_function1() { : This function does something complicated with two arguments. : : Parameters: : ' arg1 - first argument ()' : ' arg2 - second argument' : : Result: : " it's complicated" # actual function code starts here } lib_function2() { : Function documentation # function code here } # help function --help() { echo MyLib v0.0.1 echo echo Usage: mylib.sh [function_name [args]] echo echo Available functions: declare -f | sed -n -e '/^'$LIB_PREFIX'/,/^}$/{/\(^'$LIB_PREFIX'\)\|\(^[ \t]*:\)/{ s/^\('$LIB_PREFIX'.*\) ()/\n=== ===/;s/^[ \t]*: \?['\''"]\?/ /;s/['\''"]\?;\?$//;p}}' } # main code if [ "${BASH_SOURCE[0]}" = "" ]; then # the script was executed instead of sourced # invoke requested function or display help if [ "$(type -t - "" 2>/dev/null)" = function ]; then "$@" else --help fi fiнесколько комментариев о коде:
- все" публичные " функции имеют одинаковый префикс. Только они предназначены для вызова пользователем и перечислены в тексте справки.
- функция самодокументирования опирается на предыдущий пункт и использует
declare -f
чтобы перечислить все доступные функции, затем фильтрует их через sed для отображения только функций с соответствующим префиксом.- это хорошая идея, чтобы заключить документацию в одинарные кавычки, чтобы предотвратить нежелательное расширение и удаление пробелов. Вы также должны быть осторожны при использовании апострофы/кавычки в тексте.
- вы можете написать код для интернализации префикса библиотеки, т. е. пользователю нужно только ввести
mylib.sh function1
и он переводится внутриlib_function1
. Это упражнение оставлено на усмотрение читателя.- помощь функция называется "помочь". Это удобный (т. е. ленивый) подход, который использует механизм вызова библиотеки для отображения самой справки, без необходимости кодировать дополнительную проверку для
. В то же время он будет загромождать ваше пространство имен, если вы создадите библиотеку. Если вам это не нравится, вы можете либо изменить имя на что-то вроде
lib_help
или на самом деле проверить args для--help
в главном коде и вызвать функцию справки вручную.