Вопрос или проблема
Команда 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
. Хотя эта функциональность может значительно упростить рабочие процессы и улучшить читаемость кода, важно учесть её ограничения и совместимость с различными средами. Всегда следует проверять документацию и спецификации, если вы планируете использовать скрипты в разных оболочках.