for i in 'a b' 'c d'; do echo $i;done
这可以打印两行:
a b
c d
for i in $(echo "'a b' 'c d'");do echo $i;done
这将打印四行:
'a
b'
'c
d'
我尝试将数组与eval
一起使用。这有效。
eval array=($(echo "'a b' 'c d'")
for ((i=0;i<${#array[@]};i++));do echo ${array[$i]};done
这项工作做得很好并打印出两行:
a b
c d
还有另一种简单的方法吗?
我希望在$(echo“'a b''c d'”)中迭代i,就像我在'a b''c d'
中的i一样答案 0 :(得分:2)
我假设您有一些变量构造为空格分隔列表,并且您的项目可能包含空格。
正如您所看到的,在bash中迭代很难。
如果您对变量生成有任何控制权,请考虑如下:
lines="a b
c d"
( IFS=$'\n' ; for i in $lines ; do echo $i ; done ; )
如果你无法控制变量的创建,你仍然可以让它更复杂:
eval array=($(echo "'a b' 'c d'"))
for i in "${array[@]}" ; do echo $i ; done
更新 - 如下所述,有些解释是按顺序排列的:
第一个解决方案:
来自man bash:
IFS
内部字段分隔符,用于在扩展后进行单词拆分,并使用read builtin命令将行拆分为单词。默认值为``&lt; space&gt;&lt; tab&gt;&lt; newline&gt;''。
还要注意分配&lt; newline&gt;的有点复杂的方式到IFS:IFS=$'\n'
这里我们使用(
... )
将IFS的范围封装在子shell中。如果您不关心IFS的值是否会被更改,或者您设计了另一种方法来恢复其原始值,例如,您可以不使用它。 saved_ifs=$IFS ; ... ; IFS=$saved_ifs
第二个解决方案:
我们使用eval array=($(echo "'a b' 'c d'"))
而不是array=('a b' 'c d')
,因为当我们myvar="'a b' 'c d'"
(或我试过的任何其他组合)时,array=($myvar)
将无法做正确的事情(有或没有引号),但eval array=($(echo $myvar))
将被评估为array=('a b' 'c d')
。
注意"${array[@]}"
和"${array[*]}"
之间的区别;它类似于“$ @”和“$ *”之间的区别(再次来自man bash):
*从1开始扩展到位置参数。当扩展发生在双引号内时,它会扩展为单个单词,每个参数的值由IFS特殊变量的第一个字符分隔。也就是说,“$ *”相当于“$ 1c $ 2c ...”,其中c是IFS变量值的第一个字符。如果未设置IFS,则参数由空格分隔。如果IFS为null,则连接参数时不会插入分隔符。
@从1开始扩展到位置参数。当扩展发生在双引号内时,每个参数都会扩展为单独的单词。也就是说,“$ @”相当于“$ 1”“$ 2”...如果双引号扩展发生在一个单词中,则第一个参数的扩展与原始单词的开头部分连接,并且扩展最后一个参数与原始单词的最后一部分连接在一起。当没有位置参数时,“$ @”和$ @展开为空(即,它们被删除)。
答案 1 :(得分:0)
目前尚不清楚为什么你认为这里需要eval
。以下将做同样的事情:
array=('a b' 'c d')
for line in "${array[@]}"; do
echo "$line"
done