我所说的“Bashism”是指只有 bash shell 能理解而其他 shell 不能理解的 shell 语法。
如果你编写的脚本仅在/bin/bash
存在的环境中执行,那么我认为避免 Bashism 是无用的并且浪费时间,但也许我遗漏了一些东西。
如果允许使用仅在 Bash 中可用的功能,那么有更简单的解决方案,那么以更复杂的方式编写脚本有什么好处呢?
有一个后续问题:有没有关于 bash 和 dash 速度的具体数据?
我在这里发表了我的结论:https://github.com/guettli/programming-guidelines/#portable-shell-scripts
答案1
首先,可移植性。如果您确信使用脚本的任何地方都会有 bash(最好是相同或更新的版本),那就没有问题。如果您是一名开发人员或系统管理员,希望软件在 Ubuntu 以外的类 Unix 操作系统上使用,并且他们可能有也可能没有bash
,那么 bashisms 将无法被理解/bin/sh
。
第二,POSIX 合规性。如果您编写并提交脚本以将其作为操作系统或项目的一部分,则通常需要符合/bin/sh
语法,这基本上就是 POSIX 标准。 /bin/sh
出于性能原因,通常是首选,因此如果您需要 shell 脚本的速度,那么 bashisms 和 bash 可能是您应该避免的东西。
简而言之,bashism 并不坏。这实际上取决于您编写脚本的上下文。如果确定 bash 可用,并且不太过时,那么无论如何都要使用这些功能 - 它们存在是有原因的。
答案2
没什么,如果你知道你正在使用特定于 Bash 的功能,并记得使用 hashbang#!/bin/bash
而不是假设/bin/sh
是 Bash。
在 Ubuntu(和 Debian)中,脚本中的“bashisms”#!/bin/sh
主要是一个问题,当默认设置/bin/sh
更改为 Dash 而不是之前的 Bash 时(请参阅Ubuntu wiki 中的 DashAsBinSh)。所有运行的脚本/bin/sh
都必须检查是否有 bashism,并修复以使用 Dash 支持的标准功能。更改与 Bash 的可用性无关(它仍然是一个Essential
包,因此始终安装),而是与速度有关:在 systemd 之前,启动过程会产生大量 shell 脚本,将默认 shell 更改为更快的 shell 实际上会产生影响。
在其他系统上,/bin/sh
可能仍然是 Bash,因此可能会在标有 的脚本中意外使用 Bash 特有的功能#!/bin/sh
。它们无法在sh
没有 Bash 的系统中直接工作。还有一些系统根本没有 Bash。嵌入式系统通常只有 Busybox shell。非 Linux Unixen 可能没有 Bash,但它们通常有某个版本的 ksh,Bash 的许多功能都来自 ksh。但是,它们并不是 1:1 兼容的。
Bash 中的一些非标准功能非常有用(例如数组、子字符串切片 ( ${var:n:m}
)、文本替换 ( ${var/foo/bar}
)),因此如果它们使您的脚本更容易编写,请务必使用 Bash。
话虽如此,有些 bashism 有直接的标准等价物,这意味着几乎没有理由使用非标准变体。以下是一些浮现在脑海中的东西:
==
中的运算符是[ .. ]
非标准的,但相当于标准=
运算符function f { ... }
和f() { ... }
在 Bash 中是等效的,但前者是非标准的。(它来自 ksh,两者有区别。)$((--n))
是非标准的,但可以替换为$((n=n-1))
- 在简单情况下
[[ ... ]]
可以用标准替换[ .. ]