正确的Bash和Shell脚本变量大写


191

我遇到了很多都带有大写字母的变量的shell脚本,而且我一直认为这有一个严重的误解。我的理解是,按照惯例(也许很久以前就有必要了),环境变量是大写的。

但是在像Bash这样的现代脚本环境中,我一直首选使用小写的名称表示临时变量,而使用大写的名称表示导出(即环境)变量。例如:

#!/usr/bin/env bash
year=`date +%Y`
echo "It is $year."
export JAVA_HOME="$HOME/java"

这一直是我对事情的看法。是否有任何权威人士同意或不同意这种方法,或者纯粹是风格问题?

Answers:


262

按照惯例,环境变量(PAGEREDITOR,...)和内部shell变量(SHELLBASH_VERSION,...)都大写。所有其他变量名应小写。

请记住,变量名称区分大小写;该约定避免了意外覆盖环境和内部变量。

遵循该约定,您可以放心,您不需要知道UNIX工具或shell使用的每个环境变量,以免覆盖它们。如果是您的变量,则将其小写。如果导出,则将其大写。


8
+1。关于意外覆盖的要点。我忘了提,但是现在您提起它,我想我决定使用小写字母,因为我已经阅读或听说过这个问题。
JasonSmith

5
我认为使用大写变量名的主要原因是为了避免与Shell命令冲突。最近,由于脚本使用了变量“主机名”,我们意外将其中一台服务器的主机名更改为“ =”。
ThisSuitIsBlackNot 2011年

25
@ThisSuitIsBlackNot忽略糟糕的代码,变量在展开并在不能与命令名混淆的地方使用时以$为前缀。显然,执行hostname = moo会使您陷入困境。不是因为您使用的是小写的“主机名”,而是因为您没有使用正确的赋值语法。分配使用hostname = moo进行,没有空格。假设代码正确,则无需担心变量名与命令名冲突。
2011年

3
我看过的所有教科书都对所有shell变量使用大写字母。虽然允许使用小写的变量名,但约定是大写的。
布赖恩·威尔逊

3
我不知道这一点,我只损失了几个小时。USER="username"在bash脚本中使用,而不是通过ssh自动化一些远程命令user="username"。啊! 很高兴我现在知道了!
加布里埃尔·斯台普斯

28

始终遵循的任何命名约定都将有所帮助。以下是一些有关shell变量命名的有用提示:

  • 所有大写和下划线用于导出的变量和常量,尤其是在多个脚本或进程之间共享它们时。在适用的情况下,请使用通用前缀,以使相关变量脱颖而出,并且不会与Bash内部变量大写冲突。

    例子:

    • 具有共同前缀的导出变量: JOB_HOME JOB_LOG JOB_TEMP JOB_RUN_CONTROL
    • 常数: LOG_DEBUG LOG_INFO LOG_ERROR STATUS_OK STATUS_ERROR STATUS_WARNING
  • 对于范围限定于单个脚本或块的所有变量,请使用“ 小写字母 ”(全部小写和下划线)。

    例子: input_file first_value max_amount num_errors

    当局部变量与环境变量有某种关系时,请使用混合大小写,例如: old_IFS old_HOME

  • 对于“私有”变量和函数,请使用前导下划线。如果您曾经编写过一个Shell库,而其中一个库文件或多个文件中的函数需要共享变量,而又与任何与主代码中类似名称的文件都不冲突,则这尤其重要。

    例子: _debug _debug_level _current_log_file

  • 避免骆驼案。这样可以最大程度地减少因拼写错误而引起的错误。请记住,shell变量区分大小写

    例如:inputArray thisLooksBADnumRecordsProcessedveryInconsistent_style


也可以看看:


1
这是一个约定,但几乎没有被普遍接受。反对骆驼案的理由并不完全令人信服。对于导出的变量使用SHOUTING的建议存在一些争议。
Tripleee '18

3
我没有宣称这是一个普遍遵循的惯例。我已经看到,大多数程序员并不认真考虑在shell脚本中遵循强硬的约定,而是想到根据自己的所作所为写下自己的想法。
codeforester

8

如果要将Shell变量导出到环境中,则值得考虑的是POSIX(2018年第7期,版本)环境变量定义指定:

POSIX.1-2017的Shell and Utilities卷中的实用程序使用的环境变量名称仅由大写字母,数字和_可移植字符集中定义的字符中的下划线()组成,并且不能以数字开头。

...

包含小写字母的环境变量名称的名称空间保留给应用程序。应用程序可以使用此名称空间中的名称定义任何环境变量,而无需修改标准实用程序的行为。


6

我做你所做的。我怀疑是否有权威资料,但似乎是相当普遍的事实上的标准。


1
我同意。这是因为ALL_CAPS很难看,但是最好通过使环境变量脱颖而出。
苗条

1
我同意您的编码风格,但我绝对不同意它的广泛性!Shell脚本是人们只是非正式地学习的那些辅助语言之一,所以我觉得每个人都在说LOCATION =cat /tmp/location.txt
JasonSmith 2009年

@jhs-我显然很幸运,因为我不得不使用这些shell脚本!
Draemon

4
“包含小写字母的环境变量名称的名称空间保留给应用程序。” - POSIX IEEE标准1003.1-2008第8.1节
tripleee

5

实际上,术语“环境变量”似乎是最近才出现的。Kernighan和Pike在1984年出版的经典著作“ UNIX编程环境”中只谈到“ shell变量”-索引中甚至没有“环境”条目!


8
我认为这是本书的遗漏。UNIX版本7(1979)中引入了getenv(),setenv()和environ。zh.wikipedia.org/wiki/Version_7_Unix
朱利安诺

3
那本书看起来要注意大写变量确实具有特殊含义。
ashawley

3

这只是一个被广泛使用的惯例,我怀疑是否有任何“权威”来源。


1

我倾向于将ALL_CAPS用于环境和全局变量。当然,在Bash中没有真正的变量范围,因此有很大一部分变量用作全局变量(主要是设置和状态跟踪),而相对较少的“局部变量”(计数器,迭代器,部分构造的字符串和临时变量)


是的,我从概念上讲将非导出变量视为本地变量,因为Bash经常分叉子进程来完成其任务。
JasonSmith,2009年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.