Я заметил, что {
можно использовать в расширении скобок:
echo {1..8}
или в группировке команд:
{ls;echo hi}
Как Bash узнает разницу?
bash
shell-script
lovespring
источник
источник
{
это интерпретируется как список команд, если он появляется в начале команды, а в противном случае как расширение скобки, но я не уверен.{ls;echo hi}
не является законнымbash
. Вам нужен пробел после открывающей скобки и точка с запятой перед закрывающей.Ответы:
Упрощенная причина является наличие одного символа: space.
Расширения скобок не обрабатывают (не заключенные в кавычки) пробелы.
{...}
Список потребностей (ООН-цитируемый) пространства.Более подробный ответ - как оболочка анализирует командную строку .
Первый шаг для разбора (понимания) командной строки - это разделить ее на части.
Эти части (обычно называемые словами или токенами) являются результатом разделения командной строки каждого метасимвола по ссылке :
Мета-символы: spacetabenter;,<>|а &.
После разбиения слова могут иметь тип (как понимается оболочкой):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
Расширение скобки
Только если «строка скобок» (без пробелов или метасимволов) является одним словом (как описано выше) и не заключена в кавычки , она является кандидатом на «Расширение скобок». Больше проверок выполнено на внутренней структуре позже.
Таким образом, это:
{ls,-l}
квалифицируется как «расширение скобки», чтобы статьls -l
, какfirst word
илиargument
(в bash, zsh отличается).Но это не будет
{ls ,-l}
. Bash разделит spaceи проанализирует строку как два слова:{ls
и,-l}
которая вызовет acommand not found
(аргумент,-l}
потерян):Ваша строка:
{ls;echo hi}
не станет «расширением скобок» из-за двух метасимволов ;и space.Он будет разбит на следующие три части:
{ls
новая команда:echo
hi}
. Поймите, что ;запускает начало новой команды. Команда{ls
не будет найдена, и следующая команда напечатаетhi}
:Если он помещен после какой-либо другой команды, он все равно начнет новую команду после ;:
Список
Одна из «составных команд» является «Brace List» (мои слова):
{ list; }
.Как видите, он определяется пробелами и закрытием
;
.Пробелы и ;нужны потому, что оба
{
и}
являются «зарезервированными словами ».И поэтому, чтобы быть узнаваемым как слова, должны быть окружены метасимволами (почти всегда:) space.
Как описано в пункте 2 связанной страницы
Ваш пример:
{ls;echo hi}
это не список.Требуется закрытие ;и один пробел (как минимум) после {. Последний }определяется закрытием ;.
Это список
{ ls;echo hi; }
. И это{ ls;echo hi;}
тоже (менее часто используемый, но действительный) (спасибо @choroba за помощь).Но в качестве аргумента (оболочка знает разницу) команды, она вызывает ошибку:
Но будьте осторожны с тем, что, по вашему мнению, интерпретирует оболочка:
источник
;
и}
.{ ls;}
работает как точка с запятой уже мета-символ.Блок
{
является ключевым словом оболочки, поэтому он должен отделяться от следующего слова пробелом, в то время как в раскрытии фигурных скобок не должно быть пробела (если вам нужно заключить в скобки расширение пробела, вы должны его избежать:)echo {\ ,a}{b,c}
.Вы можете использовать скобки в начале команды:
Вы не можете использовать его для расширения до блока, так как синтаксический анализ команд группировки происходит перед расширениями:
источник
Это можно узнать, проверив синтаксис командной строки. Точно так же он знает, что в выражении
echo echo
первый эхо-сигнал должен рассматриваться как команда, а второй эхо-сигнал - как параметр первого эхо-сигнала.В bash это очень просто, так как
{ cmd; }
должны иметь пробелы и точки с запятой. Однако, например, в zsh они не нужны, но все же, анализируя контекст{}
оболочки, может сказать, что следует делать с ее содержимым.Учтите следующее:
Оба возвращают текущую дату, но
возвращается,
1 2 3
потому что shell знает{}
в аргументе командыecho
, поэтому должен быть расширен.источник
{
после пробела без кавычек не начинается расширение скобок в bash.{
. Пробел без кавычек не может быть нигде, потому что shell разбивает всю командную строку на пробелы.Во-первых, составная фигурная скобка должна представлять собой само слово и первое слово командной строки:
Во-вторых, отдельные фигурные скобки не являются специальными (как вы можете видеть выше). Пустые скобки тоже не особенные:
Все без запятых тоже само по себе
Здесь начинается действие.
Таким образом, в основном, для расширения скобки, нам нужно одно слово (не разделенное на поля в пустом пространстве), внутри которого есть хотя бы один экземпляр,
{...}
внутри которого есть хотя бы одна запятая.Это может быть первое слово в командной строке, кстати:
источник