bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: curiosity: 'typeset -xr' vs. 'export -r'


From: Emanuele Torre
Subject: Re: curiosity: 'typeset -xr' vs. 'export -r'
Date: Tue, 13 Dec 2022 12:38:03 +0100

On Tue, Dec 13, 2022 at 03:07:16AM -0500, Lawrence Velázquez wrote:
> Of course not.  I only meant to demonstrate that "export" always
> creates global variables, so a function that utilizes "declare -gx"
> actually behaves more like "export" then your alias does.

This is a little inaccurate.

`export' doesn't always act on the *global* variable, but "declare -g"
does.

The differences are that:
 * `declare' (without -g), always acts on variables in the current
   dynamic scope, and will create a new variable in the current dynamic
   scope if no variable with the name it was looking for exists.

 * `export' and `readonly' act on the variable they can see, and set
   their "x"/"r" attribute; they will only create a new variable (in the
   global scope) if no variable with the name they were looking for
   exists in any dynamic scope. Just like simple "a=b" assignments.

What `declare -xr' does in a function:

  fun () {
      declare -xr a=2
  }

Is equivalent to:

  fun () {
      declare a=2 && # create a new "a" variable in the current scope
                     # and set its value to 2
      export a    && # set its "x" attribute
      readonly a     # set its "r" attribute

      # when this function returns, that variable will be deleted
  }

So, as we already know, a function that runs that runs only `declare'
commands (without -p, -f, or -g) is pretty much useless.

Examples:

  bash-5.1$ # the `export' and `readonly' in "fun2" will act on the "a"
  bash-5.1$ # variable in the dynamic scope of the "fun1" function
  bash-5.1$ declare -p a
  bash: declare: a: not found
  bash-5.1$ fun1 () { local a=hi; fun2; declare -p a ;}
  bash-5.1$ fun2 () { export a; readonly a;}
  bash-5.1$ a=hello; declare -p a; fun1; declare -p a
  declare -- a="hello"
  declare -rx a="hi"
  declare -- a="hello"

  bash-5.1$ setexportreadonly () { export -- "$1" && readonly -- "$1" ;}
  bash-5.1$ x=hi
  bash-5.1$ declare -p x
  bash-5.1$ setexportreadonly x
  bash-5.1$ declare -p x
  declare -rx x="hi"

  bash-5.1$ # `declare -g' will bypass all the dynamic scopes, and will
  bash-5.1$ # act on the global variable.
  bash-5.1$ declare -p g
  bash: declare: g: not found
  bash-5.1$ fun1 () { local g=hi; fun2; declare -p g ;}
  bash-5.1$ fun2 () { declare -grx g=hey ;}
  bash-5.1$ g=hello; declare -p g; fun1; declare -p g
  declare -- g="hello" # "g" in the global scope before calling fun2
  declare -- g="hi"    # "g" in the dynamic scope of fun1 after calling fun2
  declare -rx g="hey"  # "g" in the global scope after calling fun2

  bash-5.1$ # `export', `readonly', and assignments in functions create
  bash-5.1$ # a new global variable if there are no visible variables
  bash-5.1$ # with the given name.
  bash-5.1$ declare -p v{1..5}
  bash: declare: v1: not found
  bash: declare: v2: not found
  bash: declare: v3: not found
  bash: declare: v4: not found
  bash: declare: v5: not found
  bash: declare: v6: not found
  bash-5.1$ fun1 () { local v4; fun2 "$1" ;}
  bash-5.1$ fun2 () { local v5; fun3 "$1" ;}
  bash-5.1$ fun3 () { local v6; eval " $1" ;}
  bash-5.1$ fun1 'v1=x'; fun1 'export v2=y'; fun1 'readonly v3=z'
  bash-5.1$ fun1 'v4=x'; fun1 'export v5=y'; fun1 'readonly v6=z'
  bash-5.1$ declare -p v{1..5}
  declare -- v1="x"
  declare -x v2="y"
  declare -r v3="z"
  bash: declare: v4: not found
  bash: declare: v5: not found
  bash: declare: v6: not found

 emanuele6



reply via email to

[Prev in Thread] Current Thread [Next in Thread]