Bash: for in loop with brace expansion in list
Bash: for in loop with brace expansion in list
我想编写一个 for in 循环,其中可能的值取自另一个变量。我无法弄清楚的部分是如何包含需要大括号扩展的值。例如:
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
有谁知道我如何让它工作?
非常感谢!
我担心在这种情况下您可能不得不使用 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
有时间和地点,但对于一般情况而言,这并不是最安全的方法。请参阅 Why should eval be avoided in Bash, and what should I use instead? 了解一些原因。
使用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
或者在 TEXT
而不是每个元素上使用 eval:
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
而且,正如 Tom 的回答中提到的,数组可能是更好的选择方式。
我想编写一个 for in 循环,其中可能的值取自另一个变量。我无法弄清楚的部分是如何包含需要大括号扩展的值。例如:
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
有谁知道我如何让它工作?
非常感谢!
我担心在这种情况下您可能不得不使用 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
有时间和地点,但对于一般情况而言,这并不是最安全的方法。请参阅 Why should eval be avoided in Bash, and what should I use instead? 了解一些原因。
使用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
或者在 TEXT
而不是每个元素上使用 eval:
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
而且,正如 Tom 的回答中提到的,数组可能是更好的选择方式。