更正Bash和shell脚本变量大小写

Jas*_*ith 171 bash shell scripting naming-conventions capitalization

我遇到了许多带有变量的shell脚本,我一直认为存在严重的误解.我的理解是,按照惯例(也许很久以前就必须),环境变量都是全部的.

但是在像Bash这样的现代脚本环境中,我总是倾向于使用临时变量的小写名称约定,而仅为导出(即环境)变量使用大写的约定.例如:

#!/usr/bin/env bash
year=`date +%Y`
echo "It is $year."
export JAVA_HOME="$HOME/java"
Run Code Online (Sandbox Code Playgroud)

这一直是我对事物的看法.是否有任何权威来源同意或不同意这种方法,还是纯粹是风格问题?

lhu*_*ath 233

按照惯例,环境变量(PAGER,EDITOR,...)和内部shell变量(SHELL,BASH_VERSION,...)都大写.所有其他变量名称应为小写.

请记住,变量名称区分大小写; 该惯例避免意外地覆盖环境和内部变量.

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

  • @ThisSuitIsBlackNot忽略糟糕的代码,变量在展开时以美元为前缀,并且在不能与命令名混淆的地方使用.显然,做hostname = moo会给你带来麻烦.不是因为您使用的是小写的"主机名",而是因为您没有使用正确的分配语法.使用hostname = moo完成赋值,没有空格.假设代码正确,您不必担心与命令名冲突的变量名. (23认同)
  • +1.关于意外覆盖的好处.我忘了提,但现在你提到它,我想我决定使用小写,因为我读到或听说过这个问题. (8认同)
  • 我认为使用大写变量名的主要原因是为了避免与shell命令冲突.我们最近将其中一个服务器的主机名意外更改为'=',因为脚本使用了变量'hostname'. (5认同)
  • @Seamus,“shell 变量不能覆盖环境变量”——这是错误的。尝试运行 `PATH=foo`; 即使没有“export”,您下次尝试在同一 shell 中运行“ls”或任何其他非内置命令也会失败,因为 shell 自动将更新导出到标记为导出的任何 shell 变量。也就是说,导出标志跟在变量名称后面,并且对带有标志的变量的更新会自动镜像到环境中。 (4认同)
  • 我不知道这一点,我只损失了几个小时。在bash脚本中使用`USER =“ username”`来通过ssh而不是`user =“ username”`自动执行一些远程命令。啊! 很高兴我现在知道了! (3认同)
  • @BrianS.Wilson,以前很常见,每个地方的每个人似乎都在任何 shell 脚本中编写所有大写变量。我一直在努力寻找一个 bash 标准来表明这个答案中的内容,但这仍然是我多年来实践的惯例,那是在创建资本变量多年之后;按照您在旧书中的约定中看到的方式进行操作。惯例是可以改变的,而且有时是有充分理由的。更不用说,我能想到的理论上没有理由使用大写变量,除非更有经验/时间更长的人可以解释为什么该约定开始。 (3认同)
  • 我看过的所有教科书对于所有shell变量总是用户大写。虽然允许使用小写的变量名,但是约定是大写的。 (2认同)
  • `SHELL` 不是“内部 shell 变量”。这是用户放入其环境中的值,用于指示他们对其他工具的首选 shell,类似于 EDITOR、VISUAL 的方式。和 PAGER 用于描述偏好。 (2认同)
  • @JohnPancoast,作为一名前贝尔实验室员工,据我所知,约定是确保 shell 变量与命令很容易区分开来。出于同样的原因,使用该约定仍然是一种极其常见的做法。为了清楚起见,我还没有看到任何出版的书,无论是新书还是旧书,不再次遵循这一惯例。我曾在许多公司工作过,处理过使用任一格式的 shell 代码,有时甚至混合使用这两种格式。恕我直言,使用小写变量总是使脚本更难以使用。 (2认同)

cod*_*ter 22

任何遵循的命名约定始终有用.以下是shell变量命名的一些有用提示:

  • 对导出的变量和常量使用全部大写和下划线,尤其是在跨多个脚本或进程共享它们时.在适用的时候使用公共前缀,以便相关变量突出,并且不会与全部大写的Bash内部变量冲突.

    例子:

    • 导出的变量具有公共前缀: JOB_HOME JOB_LOG JOB_TEMP JOB_RUN_CONTROL
    • 常量: LOG_DEBUG LOG_INFO LOG_ERROR STATUS_OK STATUS_ERROR STATUS_WARNING
  • 对于限定为单个脚本或块的所有变量,请使用"snake case"(全部为小写和下划线).

    例子: input_file first_value max_amount num_errors

    当局部变量与环境变量有某种关系时的混合情况,如: old_IFS old_HOME

  • 对"私有"变量和函数使用前导下划线.如果您编写一个shell库,其中库文件中的函数或跨文件需要共享变量,而不会与主代码中可能类似命名的任何内容发生冲突,那么这一点尤其重要.

    例子: _debug _debug_level _current_log_file

  • 避免骆驼案.这将最大限度地减少由错别字引起的错误.请记住,shell变量区分大小写.

    例如:inputArray thisLooksBAD,numRecordsProcessed,veryInconsistent_style


也可以看看:

  • 这是 *a* 惯例,但几乎没有被普遍接受。反对骆驼案的理由并不完全令人信服。对导出的变量使用 SHOUTING 的建议有点争议。 (4认同)
  • 我没有声称这是一个普遍遵循的惯例.我已经看到,大多数程序员并没有认真考虑遵循shell脚本中的强大约定,并且想到根据我一直在做的事情记下我的想法. (2认同)

Dra*_*mon 6

我做你做的.我怀疑这是一个权威来源,但它似乎是一个相当普遍的事实上的标准.

  • 我同意你的编码风格,但我绝对不同意它很普遍!Shell 脚本是人们非正式学习的一种辅助语言,所以我觉得每个人都在说 LOCATION=`cat /tmp/location.txt` (3认同)
  • *“包含小写字母的环境变量名称的名称空间为应用程序保留。” *-[POSIX IEEE Std 1003.1-2008第8.1节](http://pubs.opengroup.org/onlinepubs/9699919799.2016edition/basedefs/V1_chap08 .html) (2认同)

小智 5

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

  • 我认为这是本书的一个遗漏。getenv()、setenv() 和environ 是在UNIX 版本7 (1979) 中引入的。http://en.wikipedia.org/wiki/Version_7_Unix (9认同)
  • 那本书看起来注意到大写变量确实具有特殊含义。 (4认同)
  • UNIX 7th Edition 中的函数是 `getenv()` 和 `putenv()`;`setenv()` 和 `unsetenv()` 是最近添加的。 (2认同)

Ant*_*ica 5

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

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

...

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