Bash本地变量作用域最佳实践。

17
我发现有些人在编写Bash脚本时,会像示例1一样在if else语句中定义局部变量。
#!/bin/bash

function ok() {
  local animal

  if [ ${A} ]; then
     animal="zebra"
  fi

echo "$animal"
}

A=true
ok

举个例子,这个也是一样的:

例子2:

#!/bin/bash
function ok() {

  if [ ${A} ]; then
     local animal
     animal="zebra"
  fi

echo "$animal"
}

A=true
ok

因此,上面的例子打印了相同的结果,但哪一个是最好的实践?我更喜欢示例2,但我见过很多人像示例1一样在函数内部声明局部变量。是否最好像下面这样将所有局部变量在顶部声明:

function ok() {
 # all local variable declaration must be here
 
 # Next statement
 
}
2个回答

31
最好的做法是遵循以下步骤:
使用https://shellcheck.net检查您的脚本。
引用变量展开。不要使用$var,而应该使用"$var"。参考链接:https://mywiki.wooledge.org/Quotes https://www.shellcheck.net/wiki/SC2086 对于脚本中的局部变量,请优先使用小写变量名。对于export的变量,请使用大写并添加前缀以确保变量名的唯一性。
不要使用 function name(),而是使用 name()https://wiki.bash-hackers.org/scripting/obsolete(archive.org http://web.archive.org/web/20170123130003/http://wiki.bash-hackers.org/scripting/obsolete)。
记录全局变量的用法 a=true。或者在使用变量之前添加本地变量 local a; 然后 a=truehttps://google.github.io/styleguide/shellguide.html#s4.2-function-comments

作用域最佳实践

一般来说,尽量使用最小的范围。将相关内容靠近彼此。在变量使用时,将local放置在附近。这类似于C或C++的规则,即在使用时定义一个变量的附近, 但不同于C或C++,在shell中,局部声明和赋值应该分别位于不同的行上,参见https://www.shellcheck.net/wiki/SC2155
请注意,你的例子并不相同。如果变量A(或a)是空字符串,则第一个版本将打印一个空行(局部变量animal为空),而第二个版本将打印全局变量animal的值(没有local)。尽管范围应尽可能小,但animalif之外也被使用,所以local也应该在外面。

1
全局变量应该大写。虽然这只是一种约定,但我肯定可以找到相关资料。https://dev59.com/anRB5IYBdhLWcg3wSVYI 不远处就有参考资料了。它的来源是 POSIX https://dev59.com/anRB5IYBdhLWcg3wSVYI#52484424 。这是因为人们尝试在脚本中设置USER=me保留环境变量,然后得到意想不到的结果。所以最好避免使用所有大写字母的变量。https://pubs.opengroup.org/onlinepubs/007904875/basedefs/xbd_chap08.html 。对于“导出”的变量,请使用大写字母,而不是“全局”变量。 - KamilCuk
例如我所链接的stackoverflow问题:"对于所有仅适用于单个脚本或块的变量,请使用“蛇形命名法”(全部小写和下划线)",此外还有 https://google.github.io/styleguide/shellguide.html#s7.2-variable-names 。 - KamilCuk
关于大小写,我从未见过有人使用小写字母来表示全局变量的示例(但我见过很多人使用大写字母来表示全局变量)。以最新的git代码为例:https://github.com/mertcangokgoz/UsefulBashScripts/blob/master/Scripts/backup.sh。你给我的链接没有解释使用小写字母还是大写字母作为全局变量的最佳实践。 - Kalib Zen
https://github.com/Bash-it/bash-it/blob/master/install.sh#L163 你给我的链接 是哪个链接? Google ShellGuide吗? `函数名称小写,用下划线分隔单词变量名称对于函数名称也是如此。` - KamilCuk
1
你在google.github.io上的链接谈到了函数名应该小写,这是可以理解的,但它没有提到全局变量使用小写字母,最后一行你谈到了变量上的空字符串。我代码中唯一的错误是没有引用${A}测试变量以避免扩展,这只是一个在ifelse语句内运行代码的示例,因为我的原始问题是关于ifelse语句内部局部变量作用域的。我从你那里学到的唯一新东西就是不要使用function来声明函数。谢谢。 - Kalib Zen
显示剩余8条评论

1

local命令将声明的变量限制在函数作用域内

有了这个说法,你可以推断出,在if块内这样做与在外部这样做是相同的,只要它在函数内部。


但是,当您有许多本地变量时,什么是更可取和更易读的方法...难道我们不应该像Java风格一样将其声明在顶部吗? - Kalib Zen
这取决于你和你的编码风格。我也更喜欢在顶部声明变量 :) - javiervidrua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接