Bash本地AND只读变量

Azi*_*ize 7 bash

我喜欢用函数来组织代码,因为我使用函数时也喜欢使用local变量。我尽可能使用read-only变量,因此,如果我在代码内犯了任何错误,将很容易注意到。

但是我使用它已经很长时间了。所以我决定写它来分享我的经验。

如何在bash函数中定义localAND read-only?(请参阅下面的答案和解释)。

Azi*_*ize 10

第一次尝试: 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:
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

As it should be: local -r var1

This way it will do exactly what I want, I 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: 
Run Code Online (Sandbox Code Playgroud)

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

local var1="val1"
readonly var1
Run Code Online (Sandbox Code Playgroud)

  • 这(检测“本地只读...”)可能会提出一个很好的 ShellCheck 功能请求。 (4认同)
  • 另一个注意事项:在 Ubuntu 18.04 上,将 `local -r` 与数组一起使用似乎无法正确确定范围,因此如果您有两个函数,其中包含两个同名的 `local -r` 数组,则会出现错误。数组的解决方法是使用`local -ar`。 (2认同)

gho*_*oti 5

bash手册页因此总结了该declare命令的内容:

    -r   Make names readonly.  These names cannot then be assigned values
         by subsequent assignment statements or unset.
Run Code Online (Sandbox Code Playgroud)

   When used in a function, declare and typeset make each name local, as with
   the local command, unless the -g option is supplied.
Run Code Online (Sandbox Code Playgroud)

因此,如果您declare在函数内,则默认情况下,声明的变量将是局部变量。如果使用该-r选项,它将是只读的。

$ 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 -
Run Code Online (Sandbox Code Playgroud)

  • 其中一个使用比另一个少两个字节的字节来存储脚本中的命令。哦,另一个以“d”开头。:) (8认同)
  • 函数内的`declare -r` 和`local -r` 有什么区别? (4认同)