Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash local AND readonly variable

Tags:

I like to organize my code with functions, as I am using function I like to use local variables also. As much as possible I use read-only variables, so if I make any mistake inside my code it will be easily noticed.

But I have been using it wrong for a long time. So I decided to write it to share my experience.

How to define local AND read-only inside bash function? (See the answer and explanation below).

like image 856
Azize Avatar asked Jul 31 '17 07:07

Azize


People also ask

How do I create a read only variable in bash?

To add more nuance, readonly may be used to change a locally declared variable property to readonly, not affecting scope. Note: adding -g flag to the declare statement (e.g. declare -rg a="a1" ) makes the variable scope global. (thanks @chepner). Note: readonly is a "Special Builtin".

What is read only variable in bash?

Read-only VariablesShell provides a way to mark variables as read-only by using the read-only command. After a variable is marked read-only, its value cannot be changed. /bin/sh: NAME: This variable is read only.

How do I get rid of readonly variables?

An alternative if gdb is unavailable: You can use the enable command to load a custom builtin that will let you unset the read-only attribute. The gist of the code that does it: SETVARATTR (find_variable ("TMOUT"), att_readonly, 1); Obviously, you'd replace TMOUT with the variable you care about.

How do I remove a read only variable in Linux?

You can't delete mySite. The whole point of the readonly command is to make it final and permanent (until the shell process terminates). If you need to change a variable, don't mark it readonly.


2 Answers

First attempt: local readonly var1

That is the way I used to define it. It is wrong. I will define my variable var1 as local, but it will not be readonly, as you can see on example below, I can change the value of var1, and I don't want that!

:~$ ( >     myfunction() >     { >         # Define variable >         local readonly var1="val1" >          >         echo "Readonly output:" >         readonly | grep -E 'readonly|local|var1' >         echo "" >  >         echo "Local output:" >         local | grep -E 'readonly|local|var1' >         echo "" >  >         var1="val2" >         echo "VAR1 INSIDE: ${var1}" >     } >     myfunction >     echo "VAR1 OUTSIDE: ${var1}" > ) Readonly output:  Local output: var1=val1  VAR1 INSIDE: val2 VAR1 OUTSIDE: 

Second attempt: readonly local var1

This time it will define var1 as readonly, but it will also define a variable called local, so using this way it will not handle local as keyword, it will be a variable name.

Check also that the scope of var1 is not local, in fact it is global, we can see the value of var1 outside the function.

:~$ ( >     myfunction() >     { >         # Define variable >         readonly local var1="val1" >          >         echo "Readonly output:" >         readonly | grep -E 'readonly|local|var1' >         echo "" >  >         echo "Local output:" >         local | grep -E 'readonly|local|var1' >         echo "" >  >         echo "VAR1 INSIDE: ${var1}" >     } >     myfunction >     echo "VAR1 OUTSIDE: ${var1}" > ) Readonly output: declare -r local declare -r var1="val1"  Local output:  VAR1 INSIDE: val1 VAR1 OUTSIDE: val1 

As it should be: local -r var1

This way it will do exactly what I want, it will define var1 as scope local AND readonly.

:~$ ( >     myfunction() >     { >         # Define variable >         local -r var1="val1" >          >         echo "Readonly output:" >         readonly | grep -E 'readonly|local|var1' >         echo "" >  >         echo "Local output:" >         local | grep -E 'readonly|local|var1' >         echo "" >  >         #var1="val2" >         echo "VAR1 INSIDE: ${var1}" >     } >     myfunction >     echo "VAR1 OUTSIDE: ${var1}" > ) Readonly output: declare -r var1="val1"  Local output: var1=val1  VAR1 INSIDE: val1 VAR1 OUTSIDE:  

We can define it as below also, but one line is better than two!

local var1="val1" readonly var1 
like image 160
Azize Avatar answered Sep 29 '22 23:09

Azize


The bash man page summarizes things thusly for the declare command:

    -r   Make names readonly.  These names cannot then be assigned values          by subsequent assignment statements or unset. 

and

   When used in a function, declare and typeset make each name local, as with    the local command, unless the -g option is supplied. 

So if you declare within a function, the variable you declare will be local by default. And if you use the -r option, it will be read-only.

$ cat testv #!/usr/bin/env bash  test1() {   declare -r var="$1"   var="bacon" }  s=foo test1 bar echo "$s - $var"  $ bash testv testv: line 5: var: readonly variable foo - 
like image 32
ghoti Avatar answered Sep 29 '22 21:09

ghoti