Как работает расширение фигурных скобок в оболочке?

Вопрос или проблема

Команда echo {1..3}-{1,2} выводит 1-1 1-2 2-1 2-2 3-1 3-2. Я понимаю, как можно использовать фигурные скобки. Но что это на самом деле такое?

Является ли это работой sh / bash для разбора/расширения их и передачи расширенной версии выполняемой программы?

Если да, то какие еще трюки они могут выполнять, и существует ли спецификация?

Также, есть ли у этого название?

Обрабатывается ли ls *.txt аналогичным образом внутри?

Существует ли способ добиться повторения аргумента n раз? Например (не работает, конечно, только концепт): cat test.pdf{*3}cat test.pdf test.pdf test.pdf?

Это называется расширение фигурных скобок.

Это один из нескольких видов расширений, выполняемых bash, zsh и ksh, расширение имени файла *.txt также является одним из них. Расширение фигурных скобок не охватывается стандартом POSIX и, следовательно, не является переносимым. Вы можете прочитать об этом в руководстве bash.

По предложению @Arrow: для того чтобы получить cat test.pdf test.pdf test.pdf только с помощью расширения фигурных скобок, вам нужно использовать этот “хак”:

#cat test.pdf test.pdf
cat test.pdf{,}

#cat test.pdf test.pdf test.pdf
cat test.pdf{,,}

#cat test.pdf test.pdf test.pdf test.pdf
cat test.pdf{,,,}

Некоторые распространенные использования:

for index in {1..10}; do
   echo "$index"
done

touch test_file_{a..e}.txt

Или другой “хак” для печати строки 10 раз:

printf -- "mystring\n%0.s" {1..10}

Имейте в виду, что расширение фигурных скобок в bash происходит до расширения параметров, поэтому распространенной ошибкой является:

num=10
for index in {1..$num}; do
   echo "$index"
done

(оболочка ksh93 справляется с этим)

Ответ PesaThe охватывает важные аспекты вопроса. Есть несколько вещей, которые я хочу добавить.

Знак звездочки в ls *.txt обрабатывается оболочкой и, следовательно, контролируется опциями оболочки, которые могут изменяться встроенными командами оболочки. В этом случае можно отключить расширение звездочки, выполнив set -f, и снова включить его с помощью set +f.

Еще одна вещь заключается в том, что любой, кто хочет сделать скрипт переносимым, должен проверить стандарт POSIX. Например, {1..9..2} расширяется в 1 3 5 7 9 в bash 4, но не расширяется в более ранних версиях bash или в sh.

Связано: при работе с переменными расширение фигурных скобок не выполняется.

Пример, это не работает:

hosts={ab,cd,ef}-server:{80,81,82}

Мне пришлось вставить дополнительный echo

hosts=`echo {ab,cd,ef}-server:{80,81,82}`

и тогда $hosts — это переменная, содержащая расширенный список.

$ echo $hosts
ab-server:80 ab-server:81 ab-server:82 cd-server:80 cd-server:81 cd-server:82 ef-server:80 ef-server:81 ef-server:82

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

Ответ или решение

Как работает расширение фигурными скобками в командной строке?

Расширение фигурными скобками, или brace expansion, является мощным инструментом в арсенале таких оболочек, как bash, zsh и ksh. Эта функциональность позволяет пользователям создавать наборы строк, используя синтаксис фигурных скобок, что существенно упрощает написание команд и сценариев.

Основы расширения фигурными скобками

Когда вы вводите команду вроде

echo {1..3}-{1,2}

результатом будет

1-1 1-2 2-1 2-2 3-1 3-2

В этом случае оболочка интерпретирует конструкцию {1..3} как три числа (1, 2, 3) и {1,2} как два элемента (1 и 2), и последовательно генерирует все возможные комбинации, разделяя их дефисом.

Регистрация и обработка

Расширение фигурными скобками выполняется оболочкой до других типов расширений, таких как параметрное расширение. Поэтому, например, если вы используете переменную в конструкции, как в следующем примере, это не будет работать:

num=10
for index in {1..$num}; do
   echo "$index"
done

Это не сработает, потому что bash не интерпретирует переменные в контексте расширения фигурными скобками.

Расширение и совместимость

Важно отметить, что расширение фигурными скобками не является частью стандарта POSIX, поэтому оно может быть не совместимо с другими оболочками, как sh. Это подчеркивает важность проверки совместимости при разработке скриптов, которые предназначены для использования в различных окружающих средах.

Примеры использования расширения фигурными скобками

Расширение фигурными скобками абсолютно универсально и может быть использовано в самых разных сценариях. Вот несколько примеров:

  • Генерация файлов:
touch test_file_{a..e}.txt

Это создаст файлы с именами test_file_a.txt, test_file_b.txt и так далее.

  • Печать значений:
for index in {1..10}; do
   echo "$index"
done

Этот цикл выведет числа от 1 до 10 в терминале.

  • Повторение строки:

Для достижения многократного повторения аргументов существует "хака" по использованию запятых:

cat test.pdf{,}
cat test.pdf{,,}
cat test.pdf{,,,}

Каждое из этих выражений будет расширяться до cat test.pdf с различным числом повторений.

Условия и ограничения

Существует определённые моменты, о которых стоит помнить. Например:

  • Файловое расширение. В отличие от расширения фигурными скобками, обработка *.txt производится оболочкой как расширение имён файлов (filename expansion), и её поведение контролируется встроенными функциями оболочки. Чтобы отключить это расширение, можно использовать команду set -f.

  • Не все версии поддерживают все функции. Например, конструкция {1..9..2} не будет работать в некоторых версиях оболочки bash или в sh, но будет успешно выполнена в оболочке bash 4 и выше.

Заключение

Расширение фигурными скобками — это важная часть интерактивной командной строки и скриптового программирования в оболочках, таких как bash. Хотя эта функциональность может значительно упростить рабочие процессы и улучшить читаемость кода, важно учесть её ограничения и совместимость с различными средами. Всегда следует проверять документацию и спецификации, если вы планируете использовать скрипты в разных оболочках.

Оцените материал
Добавить комментарий

Капча загружается...