Самая простая оболочка для программистов на C ++ / C # / Java - PullRequest
4 голосов
/ 09 декабря 2010


Я немного борюсь с программированием на bash, потому что, похоже, я не понимаю правила синтаксиса. Например:

read confirm
if [ "$confirm" == "yes" ]; then
    echo "Thank you for saying yes"
else
    echo "Why did you say no?"
fi

В этом коде вы можете использовать много форм для одного и того же:

"$confirm" == "yes"
$confirm == "yes"
"$confirm" == yes
$confirm == yes

Так, каково правило? Кроме того, он очень строгий, поэтому, если вы напишите приведенное выше выражение if без пробела между '[' и '"', вы получите ошибку. Итак, мои вопросы:

  1. Кто-нибудь может дать мне представление об «основных» правилах синтаксиса в сценариях оболочки? Вы можете назвать это грамматикой, если хотите.
  2. Насколько я знаю, есть три различных сценария программирования оболочки. Какой из них легче всего изучить программистам таких языков, как C ++, C # и Java?

С уважением,
Рафид

Ответы [ 8 ]

12 голосов
/ 09 декабря 2010

Правила простые, но тонкие.Примеры, которые вы привели, не все эквивалентны, они имеют немного различное значение.Для достаточно хорошей справки вы можете прочитать Язык команд оболочки , который охватывает оболочки POSIX.Большинство оболочек, включая, конечно, bash, zsh и ksh, являются оболочками POSIX и будут реализовывать, по крайней мере, то, что перечислено там.Некоторые оболочки могут соответствовать более ранним версиям спецификации или быть похожими, но не совместимыми.

Основное правило, которое вам необходимо запомнить, если вы изучаете сценарии оболочки Unix, таково: выражения разделяются пробелами.Технически они разделяются теми символами, которые перечислены в переменной $ IFS, но при нормальных обстоятельствах это становится пробелом.

Если вы говорите ["$a"="$b"] в bash, оболочка пытается прочитать всю строку как команду,оценивая $ a и $ b на месте.Предполагая, что значение $a было литералом a, а значение $b было литералом b, оболочка будет пытаться выполнить команду с именем [a=b], которая является допустимым именем файла.Кавычки интерпретировались оболочкой как особые, а [ - нет, потому что они особенные, только если написаны как отдельный токен.Он не был разделен пробелами.

Почти все, что вы видите и делаете в оболочке, является командой.Символ [ это не синтаксис, это команда.Команды принимают аргументы, разделенные пробелами.Что означают эти аргументы, зависит от команды, а не от оболочки.В C if ( a == b ) обрабатывается все синтаксическим анализатором, кроме значений a и b.В bash if [ "$a" == "$b" ] сначала анализируется оболочкой, которая оценивает переменные $ a и $ b, а затем выполняется команда [.Иногда это встроенная команда оболочки, иногда это буквально отдельный исполняемый файл (ищите /bin/[ в вашей системе).Это означает, что a == b ] вообще не интерпретируется bash, а является своего рода языком, специфичным для предметной области, который интерпретируется как [, который также известен как test.На самом деле вы можете написать if test "$a" == "$b" вместо этого.В этой форме test не требует закрытия ], но все остальное тоже самое.Чтобы увидеть, что test будет делать с этими аргументами, прочитайте help test или man test.

Еще одно правило, которое следует помнить при изучении сценариев оболочки Unix, таково: переменные раскрываются первыми, команды оцениваются вторыми.Это означает, что если у вас есть пробел в переменной, такой как foo="a b", то оболочка увидит пробел после расширения переменной: ls $foo сам пожалуется, что не может найти файл a и не может найтифайл b.Чтобы получить поведение, которое вы, вероятно, ожидаете от других языков, вы почти всегда захотите заключить в кавычки свои переменные: ls "$foo", который указывает оболочке, что расширенная переменная должна обрабатываться как одна строка и не подвергаться повторному токенизации.

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

2 голосов
/ 09 декабря 2010

Все языки оболочки ужасны, хотя некоторые более ужасны, чем другие, и все лучше, чем cmd.exe Windows.Мой совет - придерживаться Bash, который является самым популярным.man bash должен дать вам (огромные, запутанные) синтаксические правила.

2 голосов
/ 09 декабря 2010

Чтобы быть в безопасности, вы должны использовать:

"$confirm" == "yes"

, поскольку это гарантирует, что bash будет считать оба значения просто строками. В противном случае они могут быть расширены / заменены, что может привести к неожиданным результатам и / или синтаксическим ошибкам.

Что касается синтаксической ошибки, когда вы пропускаете пробел между открывающей скобкой и кавычкой - открывающая скобка "[" - это просто псевдоним встроенной оболочки "test". Таким образом, ваше состояние может быть записано как:

read confirm
if test "$confirm" == "yes"; then
    echo "Thank you for saying yes"
else
    echo "Why did you say no?"
fi

Фактически, в некоторых системах в / usr / bin есть файл с именем [, который связан с тестовой командой (в случае, если в какой-либо оболочке нет «[» в качестве встроенной команды оболочки).

2 голосов
/ 09 декабря 2010
2 голосов
/ 09 декабря 2010

Самое основное грамматическое правило в bash:

<command> <space>+ <arguments>

То есть команда и аргументы должны быть разделены одним или несколькими пробелами.[ - это команда, поэтому пропустить пробел после ошибки.

Что касается "лучше", я повторяю комментарий j_random_hacker:

Все языки оболочкиУжасно, хотя некоторые более ужасны, чем другие, и все лучше, чем Windows cmd.exe.Мой совет - придерживаться Bash, который является самым популярным.

2 голосов
/ 09 декабря 2010

Одна проблема в том, что если вы сделаете:

if [ $foo == "bar" ] ...

и тогда $ foo пусто, вы получите синтаксическую ошибку. Это может быть решено, например,

# prepend both with an 'x' (or any other char)
if [ x$foo == "xbar" ] ..
# or enclosing in quotes (not sure this works on all shells)
if [ "$foo" == "bar" ] ...

Помещение содержимого в кавычки также гарантирует, что для сравнения сохраняются пробелы.

Сегодня существуют другие более продвинутые способы использования выражений внутри операторов if, например двойные скобки

if [[ $foo == bar ]]

см. этот SO вопрос для более подробной информации об этом.

Что касается выбора, какой сценарий диалекта изучать, я бы предложил изучить bash, поскольку он является наиболее распространенным. Если вы хотите писать переносимые сценарии, ограничьте себя старым диалектом 'sh', который не настолько продвинут, но должен поддерживаться почти всеми оболочками Unix.

Синтаксис C может быть более понятным для синтаксиса программистам в стиле C (так как синтаксис более точно соответствует C), но он менее распространен в дикой природе

1 голос
1 голос
/ 09 декабря 2010

Предлагаю вам проверить tcsh .Его синтаксис больше похож на C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...