Сложное расширение скобки в оболочке - PullRequest
8 голосов
/ 11 мая 2009

При использовании оболочки POSIX следующее

touch {quick,man,strong}ly

расширяется до

touch quickly manly strongly

Что коснется файлов quickly, manly и strongly, но возможно ли динамически создать расширение? Например, следующее иллюстрирует то, что я хочу сделать, но не работает из-за порядка расширения:

TEST=quick,man,strong    #possibly output from a program
echo {$TEST}ly

Есть ли способ достичь этого? Я не против приковать себя к Башу, если это будет необходимо. Я также хотел бы избежать петель. Расширение должно быть задано как полные аргументы любой произвольной программе (то есть программа не может быть вызвана один раз для каждого файла, она может быть вызвана только один раз для всех файлов). Я знаю о xargs, но я надеюсь, что все это можно как-то сделать из оболочки.

Ответы [ 4 ]

18 голосов
/ 11 мая 2009

... С использованием eval так много неправильного. То, что вы спрашиваете, возможно только с eval, НО то, что вы могли бы хотеть , легко возможно без необходимости прибегать к bash bug-central.

Используйте массивы! Всякий раз, когда вам нужно сохранить несколько элементов в одном типе данных, вам нужен (или должен использовать) массив.

TEST=(quick man strong)
touch "${TEST[@]/%/ly}"

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

Как это работает:

  • "${foo[@]}": Расширяет массив с именем foo, расширяя каждый из его элементов в правильных кавычках. Не забывайте цитаты!
  • ${foo/a/b}: Это тип расширения параметра, который заменяет первое a в расширении foo на b. В этом типе расширения вы можете использовать % для обозначения конца расширенного значения , вроде $ в регулярных выражениях.
  • Соберите все это вместе, и "$ {foo [@] /% / ly}" расширит каждый элемент foo, правильно заключит его в кавычки как отдельный аргумент и заменит конец каждого элемента на ly.
3 голосов
/ 11 мая 2009

В bash вы можете сделать это:

#!/bin/bash
TEST=quick,man,strong
eval echo $(echo {$TEST}ly)
#eval touch $(echo {$TEST}ly)

Последняя строка закомментирована, но будет касаться указанных файлов.

1 голос
/ 19 сентября 2013

Zsh может легко сделать это:

TEST=quick,man,strong
print ${(s:,:)^TEST}ly

Содержимое переменной разделяется запятыми, затем каждый элемент распределяется в строку вокруг фигурных скобок:

quickly manly strongly
0 голосов
/ 11 мая 2009

Вдохновляясь ответами выше:

$ TEST=quick,man,strong
$ touch $(eval echo {$TEST}ly)
...