Якій цілі служить вбудована кишка?


45

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

Documenation здається досить простим:

: (a colon)  
     : [arguments]  

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

Однак я раніше бачив це лише в демонстраціях розширення оболонки. Випадок використання в сценарії, на який я зіткнувся, широко використовував цю структуру:

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

Насправді було сотні грепів, але вони просто більше однакових. Ніяких перенаправлень вводу / виводу немає, крім простої структури вище. Пізніше в сценарії не перевіряються значення повернення.

Я читаю це як марну конструкцію, яка говорить "чи нічого не роблю". Якій цілі могло бути закінчення цих грепів на "чи нічого не робити"? У якому випадку ця конструкція спричинить інший результат, ніж просто відсторонення || :від усіх випадків?


10
Я бачу одну із можливих цілей - використовувати :як альтернативу true. Можливо, errexitце встановлено, і автор не переймається статусом виходу деяких команд.
jw013


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

Відповіді:


29

Здається, :замість цього у вашому сценарії використовуються s true. Якщо grepу файлі не знайдеться збіг, він поверне ненульовий код виходу; як згадується jw013 у коментарі, якщо errexitвін встановлений, ймовірно, -eпо лінії shebang, сценарій буде закритий, якщо будь-який з greps не знайде збіг. Зрозуміло, що це не те, чого хотів автор, тому він додав, || :щоб статус виходу цієї конкретної складеної команди завжди дорівнював нулю, як і звичайніший (на мій досвід) || true/ || /bin/true.


Дух. Це було в концепції сценарію складання 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: Чи маєте ви посилання на рядок "шеколон"?
l0b0

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" (с) 1984 р. Керніган та Пайк.

Сторінка 147 (програмування Shell) говорить про це:

":" - це вбудована команда оболонки, яка не робить нічого, крім оцінки своїх аргументів і повертає "true". Натомість [посилаючись на приклад сценарію], ми могли використати true , який просто повертає справжній статус виходу. (Існує також помилкова команда.) Але ':' є ефективнішою, ніж істинна, оскільки вона не виконує команду з файлової системи . [Курсив / наголос мій.]


2
Звичайно, trueзараз оболонка вбудована також у багатьох системах.
трійчатка

8

Здається, я згадую, що ранні версії оболонки не мали синтаксису коментарів. Рядок, що починається з :(що, мабуть, був би фактичним виконуваним файлом /bin/true), був би найкращою альтернативою.

Ось довідкова сторінка для давньої оболонки Томпсона (ніякого відношення); немає жодного синтаксису коментарів.


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

8

":" зручно для налагодження.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

Працюючи нормально, налагодження ніколи не виконується, тому просто переходьте через нооп (змінні та підстановки все-таки розширені). Якщо потрібна більш глибока налагодження, видаліть 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.