Bash: для в цикле с расширением скобки в списке
Я хотел бы написать цикл for, в котором возможные значения взяты из другой переменной. Часть, которую я не могу понять, состоит в том, как включить значения, которые требуют расширения скобки. Например:
TEXT="a b c d{a..c} e f"
for VAR in $TEXT; do echo $VAR; done
Что я получаю
a
b
c
d{a..c}
e
f
Но то, что я хочу, это
a
b
c
da
db
dc
e
f
Кто-нибудь знает, как я могу заставить это работать?
Большое спасибо!
3 ответа
Боюсь, что вам, возможно, придется прибегнуть к eval
в этом случае... Однако я бы посоветовал вам избежать использования цикла:
eval "printf '%s\n' $TEXT"
С помощью eval
означает, что скобки будут расширены, что приведет к желаемому результату.
Вы можете увидеть, что происходит, используя set -x
:
$ set -x
$ eval "printf '%s\n' $TEXT"
+ eval 'printf '\''%s\n'\'' a b c d{a..c} e f'
++ printf '%s\n' a b c da db dc e f
a
b
c
da
db
dc
e
f
Обратите внимание, что расширение происходит до того, как список будет передан в качестве аргументов printf
,
Если вы получите, чтобы определить $TEXT
и хотите перебрать каждый из его расширенных элементов, я бы предложил вместо этого использовать массив:
text=( a b c d{a..c} e f )
for var in "${text[@]}"; do
# whatever with "$var"
done
Это предпочтительное решение, так как оно не связано с использованием eval
,
РЕДАКТИРОВАТЬ
Пока есть время и место для eval
Это не самый безопасный подход для общего случая. См. Почему следует избегать eval в Bash, и что я должен использовать вместо этого? по ряду причин почему.
использование eval
:
TEXT="a b c d{a..c} e f"
for VAR in $TEXT; do eval echo $VAR; done
Выход:
a
b
c
da db dc
e
f
Если вы хотите перебрать каждый элемент, вам придется вложить свои циклы:
for VAR in $TEXT; do
for VAR2 in $(eval echo $VAR); do
echo $VAR2
done
done
Выход:
a
b
c
da
db
dc
e
f
Или используйте Eval на TEXT
а не каждый элемент:
TEXT="$(eval echo "a b c d{a..c} e f")"
for VAR in $TEXT; do echo $VAR; done
Выход:
a
b
c
da
db
dc
e
f
Без eval
, но с подстановкой команд:
$ text="$(echo a b c d{a..c} e f)"
$ echo "$text"
a b c da db dc e f
И, как уже упоминалось в ответе Тома, массив, вероятно, является лучшим способом.