让我们在术语上清楚。环境变量是由Bash环境设置的变量(例如 ${0},${SHELL},${SECONDS} 等),不需要用户进行设置。变量(和常量)是由用户在其 .bash_profile、.bash_rc 或特定脚本文件中设置。这些变量的范围仅限于当前解释器执行(包括任何子环境的 shell 环境或执行的 shell 脚本)。如果环境变量被取消设置或重置,则通常会失去任何特殊的含义或值。
在我写 shell 脚本、执行构建和发布以及进行一些系统管理的 30 年+ 的时间里,我见过所有上述变量样式。Unix 允许由大写和小写字符或两个字符集的任何混合组成的变量名,Linux 基于可移植性出于某些未知原因采用了同样的做法。Posix 强烈鼓励使用大写字符集,几乎所有有关 Bash 编程的文本都是如此。我的结论是,这是一种广泛采用和使用的惯例,但并非严格要求,您可以自由做出任何不良选择。
话虽如此,有些约定是由于它们的实用性和帮助程序员高效地开发有用和可维护代码而被使用的。 当我编写bash代码时:
我使用大写字母和“_”符号作为所有变量和常量名称。
我使用排版来定义和初始化所有变量(和常量),并指定变量类型(整数,只读,导出,数组,哈希等),并定义变量(和常量),这些变量是函数本地变量(不是所有东西都需要在Bash中全局)。
我在所有变量周围使用{和}字符(无论语法是否需要),以避免意外的命名错误,这是我在实践中看到的。
我现在总是使用“#!/usr/bin/env bash”,以前在没有“/usr/bin/env”可用的系统上总是使用“#!/usr/bin/bash”。
我使用"shopt -s extglob #打开扩展全局表达式",因为这在我进行正则表达式时非常有用。
我总是使用 "set -o pipefail -o nounset -o errtrace -o functrace" 来避免管道在中途失败、变量名输入错误以及容易追踪错误和函数。我知道其他人经常使用 "shopt -s inherit_errexit nullglob compat",我也可以看出这些选项的实用性。
始終使用廣泛接受的慣例和良好的編程實踐可以顯著減少調試時間,使您的代碼易於移植和維護。例如,Bash不需要定義和初始化變量,但它可以防止使用未初始化的值,讓用戶編寫更好的代碼並檢測錯誤的值名稱。
我曾经为使用所有小写字母作为变量和常量的代码工作过,我的经验是这种做法使得很难清晰地看到名称的使用情况,并且容易犯错误。我在函数名称中使用驼峰命名法(个人喜好,而非约定)。这使得我清楚地知道我正在调用一个本地函数,我已经创建或引入到环境中。
最后,我建议在从另一个文件中获取代码时使用“source”命令,而不是较旧的“.”字符。如果没有其他选项,使用此选项查找我正在获取某些内容的所有位置要简单得多。
在我的职业生涯中,我学到了很多技能,远比与这个主题相关的技能多得多(是的,我已经走得很远),但Bash是*nix系统上非常有用和普遍的编程工具。通过遵循常规惯例编写清晰和可维护的代码是职业成长的标志。