Какой цели служит встроенная кишка?


45

Я взломал множество сценариев оболочки, и иногда самые простые вещи сбивают меня с толку. Сегодня я наткнулся на скрипт, который широко использовал :встроенную (двоеточие) команду bash.

Documenation кажется достаточно простым:

: (a colon)  
     : [arguments]  

Ничего не делайте, кроме расширения аргументов и выполнения перенаправлений. Статус возврата равен нулю.

Однако ранее я видел это только при демонстрации расширения оболочки. Вариант использования в сценарии, с которым я столкнулся, широко использовал эту структуру:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

На самом деле были сотни greps, но они просто больше одинаковы. Нет никаких перенаправлений ввода / вывода, кроме простой структуры выше. Возвращаемые значения не проверяются позже в скрипте.

Я читаю это как бесполезную конструкцию, которая говорит «или ничего не делай». Какую цель может закончить эти greps с "или ничего не делать"? В каком случае эта конструкция вызовет иной результат, чем просто исключение || :из всех случаев?


10
Одна возможная цель, которую я вижу, состоит в том, чтобы использовать :в качестве альтернативы true. Возможно errexit, установлено, и автору нет дела до статуса завершения некоторых команд.
jw013


Связанная страница Stackoverflow является IMO немного более полной (так что хорошо читать как эту страницу, так и связанную страницу).
Тревор Бойд Смит

Ответы:


29

Похоже, что :s в вашем сценарии используются вместо true. Если grepсовпадение не найдено в файле, он вернет ненулевой код завершения; как упомянуто в комментарии jw013, если errexitустановлено, вероятно, -eв строке Шебанга, сценарий завершится, если какой-либо из них grepне сможет найти совпадение. Понятно, что это не то, чего хотел автор, поэтому он (ы) добавил, || :чтобы сделать состояние выхода этой конкретной составной команды всегда нулевым, как более распространенный (по моему опыту) || true/ || /bin/true.


Duh. Это было в концепции сценария сборки RPM, и хотя я не видел никакой проверки кода выхода внутри сценария, я забыл предположить, что родительский процесс может наблюдать.
Калеб

8
Если это так, я бы назвал это плохой практикой написания сценариев. Это функционально эквивалентно использованию trueвместо этого, но семантическое намерение намного яснее true. :больше подходит, когда желателен явный NOP.
jw013

По моему опыту, это обычная практика в RPM-скриптах. Наверное, не должно быть, но мы здесь.
mattdm

некоторые пуристы предпочитают :вместо trueпотому, что :это bashвстроенный, где, как trueправило, скомпилированный двоичный файл с большими издержками. обычно я использую, trueпотому что код более читабелен (аналогично я предпочитаю использовать sourceвместо .).
Тревор Бойд Смит

36

:Встроенной также полезен с расширением Баш «Заданные значения по умолчанию» оболочки, где разложение часто используется исключительно для побочного эффекта и значение расширяется отбрасывается:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}

2
Пришел сюда в поисках этого, был сбит с толку, когда увидел этот шаблон в скрипте для объявления значений по умолчанию.
окопался

21

Я могу вспомнить два места, которые я использовал :в прошлом.

while :
do
     shell commands
     some exit condition
done

Это вечная петля.

function doSomethingStub {
    :
}

Вставьте функцию-заглушку, чтобы получить правильный контроль потока на верхнем уровне.

Одно из применений, которое я видел в старые времена: вместо #!/bin/sh(или любой другой) строки вы увидите :линию. В некоторых старых ядрах Real Unix или оболочках Real Unix это использовалось бы для обозначения «Я сценарий оболочки, дай мне запустить». Насколько я помню, это было как раз тогда, когда csh создавал обычную интерактивную оболочку.


@BruceEdiger: У вас есть ссылка на линию "Шеколон"?
10

7
Наконец нашел ссылку и пояснение ": в начале сценария": faqs.org/faqs/unix-faq/faq/part3/section-16.html
Брюс Эдигер,

1
поведение в начале :очень странно. я обнаружил, что это действительно вызывает запуск сценария sh. где, когда вы запускаете скрипт без шебанга ... он пытается запустить скрипт с любой запущенной оболочкой (поэтому, если вы работаете, bashон пытается запустить его так, как bashесли бы у вас был, cshто он пытается запустить его как csh).
Тревор Бойд Смит

19

:Встроенный уже в Thompson оболочки - это документировано для Unix V6 в 1975. В Thompson оболочке :указывается метка для gotoкоманды. Если вы никогда не пытались вызвать gotoстроку, начинающуюся с , эта строка фактически была комментарием.

Bourne оболочки , предок Борна / POSIX оболочек , как мы их знаем, никогда не было , gotoчто я не знаю, но сохранил :как не-оп команды (он уже присутствует в Unix V7 ).


Точка для информативного исторического фона.
Тони Баргански

12

Я вытащил старую ссылку: «Среда программирования UNIX» (c) 1984 года Кернигана и Пайка.

Страница 147 (Shell Programming) говорит следующее:

":" - это встроенная команда оболочки, которая только выполняет оценку своих аргументов и возвращает "true". Вместо этого [ссылаясь на пример скрипта], мы могли бы использовать значение true , которое просто возвращает истинное состояние выхода. (Существует также ложная команда.) Но «:» более эффективен, чем истина, потому что он не выполняет команду из файловой системы . [Курсив / акцент мой.]


2
Конечно, trueтеперь это встроенная оболочка, также во многих системах.
tripleee

8

Кажется, я помню, что ранние версии оболочки не имели синтаксиса комментариев. Строка, начинающаяся с :(которая, вероятно, была бы реальным исполняемым файлом, похожим на /bin/true), была бы лучшей альтернативой.

Вот справочная страница для древней оболочки Томпсона (никакого отношения); нет никакого упоминания о синтаксисе комментариев.


4
Происхождение :фактически было индикатором метки для gotoкоманды в какой-то древней оболочке (я не знаю какой). Ярлык : somethingдействительно мог бы использоваться в качестве комментария, если не было совпадений goto. Практика застряла даже после того, как gotoисчезла.
Жиль "ТАК - перестань быть злым"

8

":" удобен для отладки.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

При нормальной работе отладочная функция никогда не выполняется, поэтому просто перешагиваем noop (переменные и подстановочные знаки раскрываются). Если требуется более глубокая отладка, удалите noop из переменной, и отладочная функция вызывается с любыми необходимыми аргументами.

Еще одно удобное использование - это блочный комментарий, который отсутствует в синтаксисе оболочки.

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.