【问题标题】:How to iterate through string one word at a time in zsh如何在zsh中一次遍历一个单词
【发布时间】:2014-06-03 04:03:54
【问题描述】:

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

things="one two"

for one_thing in $things; do
    echo $one_thing
done

我希望输出是:

one 
two

但如上所述,它输出:

one two

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

【问题讨论】:

  • 这是否意味着当zshfor 循环的列表时,$things 不是分词?它是否只进入循环体一次?回答,通过配置脚本战斗后,是“是”。从可用的 shell 列表中划掉zsh;这太像非POSIX-shell了。我什至懒得开始思考如何配置它以“正常”工作。
  • 你可能不喜欢它,但这种行为完全符合 POSIX,据我所知,这是 sh shell 的预期行为。

标签: while-loop zsh expansion


【解决方案1】:

为了查看与 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?

【讨论】:

  • 除了全局设置shwordsplit之外,您还可以使用${=things}为单个参数启用sh风格的分词(当然是使用IFS)。
  • @chepner,那会是什么样子?我尝试了IFS=' '; for one_thing in ${=things}; do,但得到了bad substitution 错误
  • @RobBednark 为什么不使用数组?
  • 应该是for one_thing in ${=things}; do。您使用的是哪个版本的zsh?在 4.3.10 中为我工作。不过,数组是一个更好的主意,因为您不必依赖使用任何单个项目中都不存在的字符串分隔符。
  • @chepner,我使用的是 zsh 5.0.2 (x86_64-apple-darwin13.0)
【解决方案2】:

您可以使用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;即使是多行字符串。

    【讨论】:

      【解决方案4】:

      另一种方式,也可以在 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

      【讨论】:

        猜你喜欢
        • 2011-02-15
        • 1970-01-01
        • 2010-10-04
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 2018-02-13
        • 2020-09-17
        相关资源
        最近更新 更多