zsh is not splitting by IFS after parameter expansion
Asked Answered
C

2

6

This is my code to loop over colon separated values and do something with each value.

f()
{
    IFS=:
    for arg in $1
    do
        echo arg: $arg
    done
}

f foo:bar:baz

This works fine in most POSIX compliant shells.

$ dash foo.sh
arg: foo
arg: bar
arg: baz
$ bash foo.sh
arg: foo
arg: bar
arg: baz
$ ksh foo.sh
arg: foo
arg: bar
arg: baz
$ posh foo.sh
arg: foo
arg: bar
arg: baz
$ yash foo.sh
arg: foo
arg: bar
arg: baz

But it does not work as expected in zsh.

$ zsh foo.sh
arg: foo:bar:baz

Is zsh in violation of POSIX here?

Chaulmoogra answered 20/9, 2017 at 5:28 Comment(2)
Yes, zsh is knowingly and intentionally in violation here. That said, relying on string-splitting isn't a good practice in any shell -- even in bash, I'd encourage you to use read -r -a args <<<"$1" or such to read into an array, then for arg in "${args[@]}"; do ...Loathing
This is a case where zsh does what POSIX should do, it POSIX hadn't been burdened with maintaining existing behavior as much as possible. As the worst possible solution, you could use setopt SH_WORD_SPLIT to restore the POSIX behavior.Florey
F
3

Yes. Zsh has chosen its own way.

Here is the zsh faq entry: “3.1: Why does $var where var="foo bar" not do what I expect?”

In this particular case, you could workaround by adding the -y option to the zsh invocation:

$ zsh -y foo.sh
arg: foo
arg: bar
arg: baz

You could take a look at the zsh's faq especially the chapter 2 and 3. The more you've experienced other shells, the more you can find zsh's pitfalls.

Flapdoodle answered 20/9, 2017 at 6:17 Comment(0)
H
2

In Zsh it is usually cleaner to split with the provided (s) flag (vs using IFS). A solution for your data would then be:

% f() { for e in ${(s.:.)1}; print $e }
% f foo:bar:baz
foo
bar
baz

See the PARAMETER EXPANSION section in zshexpn(1) man page for more details and related flags.

(I assume you mean colon-separated values.)

Hooray answered 20/9, 2017 at 21:19 Comment(1)
I felt quite ok writing shell command scripts using Ruby... and then I tried to learn more Bash and Zsh,,, but they seem like Martian language to meRepletion

© 2022 - 2024 — McMap. All rights reserved.