1

我想编写一个 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

有谁知道我怎样才能让它工作?

非常感谢!

4

3 回答 3

5

我担心您可能不得不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.

于 2016-03-01T12:40:30.953 回答
2

编辑

虽然有时间和地点eval,但对于一般情况,这不是最安全的方法。请参阅为什么在 Bash 中应避免使用 eval,而我应该使用什么?出于某些原因。


使用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

或者使用 evalTEXT而不是每个元素:

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
于 2016-03-01T12:43:28.563 回答
0

没有eval,但有命令替换:

$ text="$(echo a b c d{a..c} e f)"
$ echo "$text"
a b c da db dc e f

而且,正如汤姆的回答中提到的,数组可能是更好的方式。

于 2016-03-01T14:40:48.500 回答