在zsh中,IFS的行为与bash不同

10
foo() {
    local lines=$(ls -l)
    local IFS=$'\n'
    for line in $lines; do
        echo $line
    done
}

在zsh中,循环仅执行一次,因为ls -l命令的输出没有按新行分割,整个文本块传递到了$line。然而,在bash中这个命令可以正常工作。如何在两个shell中实现完全相同的行为?
我不是在寻找“ls”输出的替代循环解决方案。只是试图理解为什么它在zsh中不能工作但在bash中完美地工作。可以使用除“ls”命令之外的任何其他命令,例如“ps -a”。行为是相同的。输出没有按行分割。
谢谢!

2
顺便问一下:为什么不解析ls - Cyrus
将您的解决方案发布为答案,我会接受它。 是的,我对shell编程毫无经验。我是一名程序员,了解shell编程只是有用的。我试图提高这个专业领域的水平。我发现学习它相当困难,因为文档相当分散,即使要获得最基本的知识,也必须阅读多个来源。 - Viorel
阅读重复链接,@Viorel。这里的问题是引用,您根本不需要调整IFS。 - pvg
@pvg 我不知道是谁将这个问题标记为重复,但显然他完全没有注意到我的问题。正确的答案是由gniourf_gniourf给出的。 - Viorel
@pvg 不,它根本不涵盖我的情况。 - Viorel
显示剩余12条评论
1个回答

15

ZSH默认情况下不会像其他Shell一样自动拆分单词:

foo() {
    local lines=$(ls -l)

    local IFS=$'\n'
    if [ $ZSH_VERSION ]; then
      setopt sh_word_split
    fi

    for line in $lines; do
        echo line: $line
    done
}

foo

感谢@chris-johnsen提供他的答案链接. 我支持他更好地使用数组(在可能的情况下)的论点:

local lines=("$(ls -l)")

其他选项(仅适用于ZSH):

  • local lines=("${(f)$(ls -l)}"),其中(f)(ps:\n:)的缩写。
  • for line in ${=lines}; do(请注意添加了等号符号)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接