ericbn
ericbn

Reputation: 10998

Assignments to variables get printed on stdout in zsh script

This is an example script that reproduces the issue:

example.zsh

zmodules=(foo bar/baz)

local zmodule
for zmodule (${zmodules}); do
  local zurl zname
  zname=${zmodule##*/}
  case ${#zmodule//[^\/]/} in
    0) zurl="https://github.com/foo/${zmodule}" ;;
    1) zurl="https://github.com/${zmodule}" ;;
  esac
  print "${zurl} ${zname}"
done

The current result of running the script:

$ source ./example.zsh 2>/dev/null
zmodule=bar/baz
zurl=https://github.com/bar/baz
zname=baz
https://github.com/foo/foo foo
zurl=https://github.com/foo/foo
zname=foo
https://github.com/bar/baz baz

Expected result:

$ source ./example.zsh 2>/dev/null
https://github.com/foo/foo foo
https://github.com/bar/baz baz

What am I missing here?

EDIT: I guess I got it: local only works inside functions. But why is it printing the assignments anyway when I declare the variables local?

Upvotes: 7

Views: 786

Answers (2)

Phil Hord
Phil Hord

Reputation: 13170

In zshell, the local/typeset commands display the value of any variable which is already defined. Your local definition command is executed multiple times, and the latter ones print the value of the variables instead of making them local as you wanted. You can disable this feature with the TYPESET_SILENT shell options.

setopt TYPESET_SILENT

Upvotes: 2

PesaThe
PesaThe

Reputation: 7519

It's because you are executing local repeatedly in the for loop. From man zshbuiltins:

local

Same as typeset, except ...

typeset

Set or display attributes and values for shell parameters.

Consequently, executing local var (without any assignment) will cause zsh to display attributes and values of that variable if it already exists. See this snippet demonstrating that behavior:

$ local var
$ var=10
$ local var
var=10
$ local var=15
$ local var2=20 var
var=15

Side note: you may be asking why both assignments are being printed whereas in my example, the first local doesn't print anything. That is because you are using source to run the script so the variables are already set from your previous attempts.

Upvotes: 8

Related Questions