Расширение фигурной скобки с помощью переменной Bash — {0..$foo}

WEEKS_TO_SAVE=4
mkdir -p weekly.{0..$WEEKS_TO_SAVE}

дает мне папку с названием еженедельно.{0..4}

Есть ли секрет расширения фигурных скобок при создании папок, которые мне не хватает?


person xref    schedule 18.02.2012    source источник


Ответы (5)


bash выполняет brace expansion перед variable expansion, поэтому вы получаете weekly.{0..4}.
Поскольку результат предсказуем и безопасен (Не доверяйте вводу пользователя), вы можете использовать eval в своем случае:

$ WEEKS_TO_SAVE=4
$ eval "mkdir -p weekly.{0..$((WEEKS_TO_SAVE))}"

примечание:

  1. eval это зло
  2. используйте eval осторожно

Здесь $((..)) используется для принудительного вычисления переменной как целочисленного выражения.

person kev    schedule 18.02.2012
comment
Я почти отрицаю это из-за использования eval. Я бы посчитал правильным цикл C-sytle for, но это единственный способ выполнить его, запустив mkdir только один раз. - person jordanm; 18.02.2012
comment
Что не так с евэлом? Все, что вы делаете в bash, опасно, eval не делает хуже. - person user123444555621; 18.02.2012
comment
@kev Я погуглил «eval is evil» и нашел: достойные сценарии составляют крошечный процент фактического использования eval. В большинстве случаев eval используется как кувалда, отбивающая муху, — он выполняет свою работу, но слишком сильно. Это медленно, громоздко и имеет тенденцию увеличивать ущерб, когда вы совершаете ошибку. Так это достойный случай или другие варианты, перечисленные здесь, лучше? - person xref; 21.02.2012
comment
Эта цитата говорит о JScript (т.е. MS JavaScript). Здесь вырвано из контекста. - person Grault; 05.06.2013
comment
@ user123444555621, нет, не все, что вы делаете в bash, опасно. Расширение параметра происходит после анализа кавычек, подстановки команд, перенаправления и т. д.; таким образом, данные из расширения параметра не могут вызывать новые подкоманды, включая $(rm -rf /), или записывать в файл, включая >/etc/passwd... если вы не используете eval, и в этом случае эти данные анализируются как код. - person Charles Duffy; 09.11.2015
comment
@Grault, это точно даже здесь; см. выше, а также BashFAQ #48 (mywiki.wooledge.org/BashFAQ/048). - person Charles Duffy; 09.11.2015
comment
@CharlesDuffy С практической точки зрения, 95%+ сценариев bash, которые я вижу в реальных производственных средах, опасны (не говоря уже о глючных, уродливых, нечитаемых, ...). Попытка бороться с этим, запрещая «eval», подобна борьбе с океаном песочным замком. Единственный реальный ответ, который я видел, - это перейти к среде программирования, которая поддерживает более строгую грамматику и контроль ошибок. - person dash-o; 10.12.2019
comment
Я понимаю, что $((..)) заставит его выполнять арифметическое расширение, но почему мы должны использовать $((WEEKS_TO_SAVE)) вместо простого $WEEKS_TO_SAVE, что может $WEEKS_TO_SAVE потенциально повредить - person Oscar Zhang; 15.06.2020

Фигурные скобки не поддерживают переменные в BASH, вы можете сделать это:

 for (( c=0; c<=WEEKS_TO_SAVE; c++ ))
 do
    mkdir -p weekly.${c}
 done
person anubhava    schedule 18.02.2012

Другой способ сделать это без eval и вызвать mkdir только один раз:

WEEKS_TO_SAVE=4
mkdir -p $(seq -f "weekly.%.0f" 0 $WEEKS_TO_SAVE)
person jfg956    schedule 18.02.2012
comment
Бу, шипение; Не работает, если в строке формата есть пробелы или другие символы в IFS. - person Charles Duffy; 09.11.2015

расширение скобок не поддерживает его. Вам нужно будет сделать это с помощью цикла.

Расширение фигурных скобок выполняется перед любыми другими расширениями, и в результате сохраняются любые символы, характерные для других расширений. Он строго текстовый. Bash не применяет синтаксическую интерпретацию контекста расширения или текста между фигурными скобками. Во избежание конфликтов с расширением параметра строка «${» не считается подходящей для раскрытия фигурных скобок.

.

person amit_g    schedule 18.02.2012

Если на вашем компьютере установлено zsh, ваш написанный код будет работать с Z-shell, если вы используете #!/bin/zsh в качестве интерпретатора:

Пример

$ WEEKS_TO_SAVE=4
$ echo {0..$WEEKS_TO_SAVE}
0 1 2 3 4
person SiegeX    schedule 18.02.2012