Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assignments to variables get printed on stdout in zsh script

Tags:

shell

zsh

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?

like image 516
ericbn Avatar asked Jan 17 '18 15:01

ericbn


1 Answers

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.

like image 135
PesaThe Avatar answered Sep 23 '22 03:09

PesaThe