如何在zsh中一次遍历字符串一个单词

问题描述 投票:21回答:4

如何修改以下代码,以便在zsh中运行时扩展$things并一次迭代一次?

things="one two"

for one_thing in $things; do
    echo $one_thing
done

我希望输出为:

one 
two

但如上所述,它输出:

one two

(我正在寻找在bash中运行上述代码时获得的行为)

bash while-loop zsh expansion
4个回答
41
投票

要查看与Bourne shell兼容的行为,您需要设置选项SH_WORD_SPLIT

setopt shwordsplit      # this can be unset by saying: unsetopt shwordsplit
things="one two"

for one_thing in $things; do
    echo $one_thing
done

会产生:

one
two

但是,建议使用数组来产生分词,例如,

things=(one two)

for one_thing in $things; do
    echo $one_thing
done

您可能还想参考:

3.1: Why does $var where var="foo bar" not do what I expect?


7
投票

您可以使用z变量扩展标志对变量进行分词

things="one two"

for one_thing in ${(z)things}; do
    echo $one_thing
done

在“参数扩展标志”下的man zshexpn中阅读有关此变量和其他变量标志的更多信息。


3
投票

您可以假设bash上的内部字段分隔符(IFS)为\ x20(空格)。这使得以下工作:

#IFS=$'\x20'
#things=(one two) #array
things="one two"  #string version

for thing in ${things[@]}
do
   echo $thing
done

考虑到这一点,您可以通过多种方式实现它,只需操作IFS即可;甚至在多行字符串上。


1
投票

另一种方法,也可以在Bourne shell(sh,bash,zsh等)之间移植:

things="one two"

for one_thing in $(echo $things); do
    echo $one_thing
done

或者,如果您不需要将$things定义为变量:

for one_thing in one two; do
    echo $one_thing
done

使用for x in y z将指示shell循环遍历单词列表y, z

第一个例子使用command substitution将字符串"one two"转换为单词列表one two(无引号)。

第二个例子是没有echo的同样的事情。

这是一个不起作用的例子,更好地理解它:

for one_thing in "one two"; do
    echo $one_thing
done

注意引号。这将只是打印

one two

因为引号意味着列表中有一个项目,one two

© www.soinside.com 2019 - 2024. All rights reserved.