В чем смысл конечного «:» (двоеточия) в * nix?

В настоящее время я следую учебнику по сценариям оболочки, расположенным здесь: http://www.cs.columbia.edu/~sauce/tutorial/ashell.html, и я считаю, что мой скрипт соответствует именно этому. Однако, когда я пытаюсь запустить пример, мой вывод не совпадает. Поскольку я не хочу быть расплывчатым и просто спрашиваю: «Почему он не работает?», Я сосредоточусь на той части, которую я не понимаю: почему существует ":" после команды testlogin: Я прочитал много форумов, которые обсуждают значение " : " (с пробелами с обеих сторон), а также ведущий ":" , но никто не упоминает использование отстающего двоеточия. В чем смысл этого контекста? И если это опечатка, может ли кто-нибудь помочь мне найти еще одну опечатку в примере, который может заставить ее работать неправильно?

Любая помощь будет принята с благодарностью!

код (скопированный точно с сайта, который я связал выше) приведен ниже:

 #testlogin useron(){ if ( who | grep $1 > /dev/null) then echo $1 is logged in else echo $1 is not logged in fi } if test $# != 1 then echo testlogin: username else useron fi 

и выход

 paul@paul-LC22UP:~$ .testlogin paul Usage: grep [OPTION]... PATTERN [FILE]... Try 'grep --help' for more information. is no logged in 

testlogin – это не команда здесь, а аргумент для echo . Полная команда:

  echo testlogin: username 

echo просто выплескивает текст, который вы передаете ему в STDOUT. Таким образом, двоеточие не имеет особого значения, оно является частью вербального вывода echo . Это вывод, если вы вызываете скрипт с неправильным количеством аргументов:

 $ ./testlogin testlogin: username $ ./testlogin fred bill adam testlogin: username 

Это странный вывод, но не обязательно опечатка. Я обычно ожидал бы чего-то большего, чем:

 $ ./testlogin Usage: testlogin username 

Причина, по которой весь скрипт не работает, заключается в том, что автор сделал тонкую ошибку при вызове функции useron и предположительно не протестировал свой скрипт перед публикацией (или они заметили бы ту же ошибку, что и вы). $1 в функции useron является первым аргументом этой функции , а не всем скриптом; но поскольку useron не вызывался с любыми аргументами, то есть пустая строка, и поэтому она заканчивает выполнение команды:

 $ who | grep 

который даст информацию об использовании grep s, а затем всегда вызывает ветвь else . Вы можете исправить это, передав первый аргумент скрипту в useron следующим образом:

 else useron $1 

Сайт, на который вы ссылаетесь, имеет очень низкокачественные shell scripts .
Чтобы ответить на ваш вопрос вверх, «трейлинг-двоеточие» не имеет особого значения для оболочки, это всего лишь часть строки, которая будет напечатана на экране.

Однако код на странице имеет такие недостатки:

  • Самая важная проблема, которую вы должны изучить, – это «цитата ваших расширений».
    Это «Расширения параметров» (переменная), но также и другие расширения.
    Это главная причина, по которой я пишу это. Очень плохо привыкать к тому, чтобы не процитировать расширения.

  • В любом месте страницы нет упоминания о механизме shebang . (это означает, что у вас есть первая строка вроде #! / bin / bash или аналогичная). Написание сценариев без указания типа оболочки, предназначенной для их запуска, является верным источником ошибок и проблем.

  • В строке № 11 отсутствует аргумент, который используется для вызова функции. Это должно быть что-то вроде: else useron "$1" вместо else useron

После этих трех явных ошибок мы можем запустить скрипт:

 $ testlogin testlogin: username 

Как вы можете видеть, строка в строке 10 печатается так же, как на консоли.
Задний двоеточие : ничего не значит для оболочки, что становится ясным, когда строка цитируется как это:

 then echo "testlogin: username" 

На самом деле, ИМО, было бы еще более явным:

 then echo "A parameter is needed, type something like 'testlogin: username'" 

Теперь выполнение скрипта без аргумента печатает полезный ответ.
И запись имени пользователя также работает:

 $ testlogin joe joe is not logged in 

Сценарий с приведенными выше изменениями:

 #/bin/sh useron(){ if ( who | grep "$1" > /dev/null) then echo "$1 is logged in" else echo "$1 is not logged in" fi } if test "$#" != "1" then echo "Parameter missing, type something like 'testlogin: username'" else useron "$1" fi 

Теперь, для второго раунда вопросов:

  • Контрольная внешняя команда не использовалась большинством снарядов.
    Он был заменен полностью эквивалентным [ или [[ в более современных оболочках. Строка, используемая в скрипте: if test "$#" != "1" должен быть заменен на:

     if [ "$#" != "1" ] 
  • Теперь мы переходим к стилю письма. В наше время чаще встречается сценарий, написанный таким образом (но это вопрос личных предпочтений):

 #/bin/sh useron(){ if ( who | grep "$1" > /dev/null); then echo "$1 is logged in" else echo "$1 is not logged in" fi } if [ "$#" != "1" ]; then echo "Parameter missing, type something like 'testlogin: username'" else useron "$1" fi