bash-скрипты: использование пробелов

Если вы хотите запустить команду и выйти из нее позже, вы можете запустить ее в отдельной оболочке:

bash -c 'tcpdump -xli eth0 | while read buffer; do
      if true; then exit; fi
    done'
2
15.10.2019, 10:29
3 ответа

"WHITE SPACE in bash is only the tip of the iceberg. Below is parser bison, and yak, and unix functions like exec() and open() and dup()."

БЕЛОЕ ПРОСТРАНСТВО имеет двойное двойное значение :Белый, как айсберг. И ASCII Nr.20 , также известный как space, является мгновенной иллюстрацией его семантической силы.

Я оставил комментарии к ответу Икки. Я еще раз повторяю, что здесь он дает хорошую пятерку за OQ.


Ниже я не буду утруждать себя написанием туториала. Я не соревнуюсь с другим Q напрямую, это скорее «другая сторона…» У меня самого есть родственный Q, вчера, о, в конце концов, это правая -на -левая конструкция:

{ tac;} < <(<FILE cat)

Я согласен с очень глупой групповой командой с перенаправлением ввода. tac FILEвыводит то же самое. Начиная с этого вопроса, я многому научился.

<FILE cat|{ tac|cat;}

...как перевернуть его изнанкой -вверх. И все это просто пируэты использования метасимволов, чтобы показать, что такое синтаксический (так -так называемый )WS. В ДРУГИХ ОБСТОЯТЕЛЬСТВАХ я скорее переверну мир вверх дном и просто напишу

cat FILE | tac >OUT

(Притворяться трубой нужно, а кот это не просто кот...теперь группировка пропала...)


Вам нужно изучить собственно грамматику, синтаксис.

Когда bash анализирует входную строку (с ), он «использует» пробелы и поэтому -называет метасимволы (двумя важными:|и>)для формирования слов. Это на самом деле очень естественно.

(We humans) do-it-"too when".we.read.В этом мы тоже хороши.

Bash имеет сложный синтаксис и свободную форму. Есть отношение. Bash использует yacc/bison для разбора кода, так же как браузер должен сначала разобрать теги html. Только после этого идет обработка или рендеринг этого символа или всей этой таблицы. Теги могут быть внутри тегов.

90% пробельных «правил» логичны и очевидны. Хотя есть некоторые ловушки. Вы нашли два из них.

Сосредоточьтесь на таких определениях, как:(простая )команда, конвейер, список, И -ИЛИ -список, составная команда, расширение слова. Перенаправление. Верхняя часть инструкции bash. Рисуй, пой, пробуй. Сначала более простые вещи.

Это самый сложный пример:

echo hello world
echo "hello world"
echo "hello" "world"

Все равно? Это не так, но это составляет. Это как 2+2=2х2. Получается 4 в обе стороны. Но это не значит, что вы можете проделывать трюк с любым другим числом или командой, кроме эха. Некоторые глубокие мыслители даже навсегда теряются в этойecho hello worldдыре . И это действительно самое простое «Привет, мир!» программа. Я стараюсь не анализировать слишком много. Я смотрю на свой терминал с черным фоном и говорю :, на самом деле это все равно DARKSPACE.

Пробел либо разделяет слова или токены, либо защищается кавычками или обратной косой чертой.

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

Новая строка — это специальный пробел, заменяющий точку с запятой . Оба имеют решающее значение, когда задействовано более одной команды, т.е. в многострочном -сценарии или в этом определении составной команды { cmd-list;}, определяющем групповую команду. Правильные имена (группа, список, блок, ИЛИ -список,...)не имеет большого значения.

Пробелы являются основным элементом синтаксиса в bash. Не волнуйтесь, если это сложно.


Дито на естественном языке:

"MS Windows" как MICROSOFTWINDOWS также является "микро Softwindows", и если "Softwindows" - это какая-то единица "Sw", то "msw" имеет смысл ДВУМЯ смыслами.

Символически используйте ms wили (m s) wдля выражения первого и m swили m (s w)для второго. Как-то. Пробел, новая строка, круглые скобки, фигурные скобки. И пусть это будет просто и красиво.

-1
27.01.2020, 21:55

Ключевым моментом является то, что пробелы разделяют слова , если они не заключены в кавычки, а слова — это то, о чем вам нужно подумать:

Basically, the shell does the following:

  1. Reads its input [...]
  2. Breaks the input into words and operators, obeying the quoting rules described in Quoting. These tokens are separated by metacharacters. [...]
  3. Parses the tokens into simple and compound commands (see Shell Commands).

- 3.1.1 Shell Operation

И:

A simple command is the kind of command encountered most often. It’s just a sequence of words separated by blanks, terminated by one of the shell’s control operators[.] - 3.2.1 Simple Commands

И:

  1. The words that the parser has marked as variable assignments (those preceding the command name) and redirections are saved for later processing.
  2. The words that are not variable assignments or redirections are expanded [...]. If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments.

- 3.7.1 Simple Command Expansion

Обратите внимание, что здесь написано «слова, [...] помеченные как присвоения переменных». Таким образом, присваивание переменной должно состоять из одного слова, поэтому следующие просто присваивания переменной:

  • var=value
  • var=" value"

Но следующее не является:

  • var= value✗ (два слова :назначение переменнойvar=-назначение пустой строки -для командыvalue)
  • var =value✗ (два слова :команда varс аргументом=value)
  • var" =value"✗ (одно слово :, но имена переменных нельзя заключать в кавычки, так что это команда с именемvar =value)
  • "var=value"✗ (одно слово :, но имена переменных нельзя заключать в кавычки, так что это команда с именемvar=value)

Теперь для [ var = value ], [есть команда (та же команда, что и test), которая ожидает проверки и операнды для проверки как отдельные аргументы . Таким образом, вы можете делать такие вещи, как [ "$var" = "$value" ]или test "$var" = "$value", где, например, var="a = b"и value="b = c"могут содержать вещи, которые выглядят как тесты, но таковыми не являются, потому что каждый из них является одним аргументом.

Поскольку аргументы должны быть отдельными словами, вокруг =необходимы пробелы. И именно поэтому "$var"и "$value"пришлось цитировать,в противном случае оболочка разбила бы их на отдельные слова, и [не удалось бы выполнить.

2
27.01.2020, 21:55

However I'd like to understand general logic behind usage of whitespace in bash scripts

Пробел обязателен при разделении аргументов на команды, а также при разделении ключевых слов(или зарезервированных слов, в зависимости от источника ). Это {, }, !, if, for, do, doneи т. д.

Пробел не обязателен вокруг операторов . Это, по крайней мере, терминаторы операторов ;и &; условные операторы &&и ||; все операторы перенаправления >, <<и т.д.; и круглые скобки (и ). Необязательный номер дескриптора файла перед оператором перенаправления не должен быть разделен пробелом, но в противном случае дополнительные пробелы вокруг операторов обычно не имеют значения.

Итак, все в порядке:

true;true
cat<<file
true&&false
tac|rev
f()(echo foo)

Это не:

if !somecmd; then...
f(){echo foo}

Первый будет искать команду !somecmdвместо запуска somecmdи инвертирования статуса выхода. Второй не работает, потому что ключевые слова '{' и }должны быть отдельными словами, и они распознаются только в начале команды. Это может быть, например. f(){ echo foo;}.

И это, если курс не работает как оператор if, потому что, если бы ifбыло выбрано с начала слова, программу с именем ifconfigбыло бы трудно использовать:

ifsomecmd;then...

(Хотя это, вероятно, очевидно, если только вы не привыкли к Фортрану.)

Откуда вы знаете, что (— оператор, а {— нет? Вы учите это наизусть. Разница может быть связана с историческими причинами, как и во многих других случаях.См.:Почему группе команд скобок нужны пробелы после открывающей скобки в грамматике оболочки POSIX?

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


Однако ничто из вышеперечисленного не поможет вам понять разницу между заданием foo=barи тестом [ "$foo" = bar ].

Суть здесь в том, что [похожа на обычную команду, она принимает свои операторы и операнды как отдельные аргументы и на самом деле не заглядывает внутрь них. Точно так же, как ls -l /somedirectoryнуждается в пробеле для разделения своих аргументов(-lи /somedirectory), так и [. Пара квадратных скобок не является частью синтаксиса оболочки(или грамматики ), равно как и =, в отличие от эквивалентной конструкции в большинстве реальных языков программирования.

Что касается задания, то оно немного сложное. Назначения не обязательно должны быть одни в командной строке (, их можно использовать с командой ), и в строке может быть более одного назначения. Вот так:

$ foobar=123 foofoo=456 env|grep foo
foofoo=456
foobar=123

То, как это работает (примерно ), заключается в том, что оболочка разбивает команду на слова (выше, это будут foobar=123, foofoo=456и env), и смотрит на начальные слова. чтобы увидеть, похожи ли они на задания. Те двое делают, но здесь нет присваивания, просто обычный аргументecho:

$ echo foo=bar
foo=bar

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

foobar = 123 foofoo = 456 env
4
27.01.2020, 21:55

Теги

Похожие вопросы