在 shell 脚本中表示布尔值的最佳实践是什么?

Min*_*nix 20 shell shell-script

我知道,在 中有布尔值bash,但我从未看到它们在任何地方使用。

我想为我的机器上一些经常查找的信息编写一个包装器,例如,这个特定的 USB 驱动器是否已插入/安装。

实现这一目标的最佳实践是什么?

我主要想知道,想要使用包装器的其他人会期望什么。他们会期望一个布尔值,一个像变量这样的命令还是一个要调用的函数?

从安全的角度来看,我认为第二种选择是最安全的,但我很想听听您的经验。

mik*_*erv 5

bool(){ return "$((!${#1}))"; }

if bool "$var"
then : do true
else : do false
Run Code Online (Sandbox Code Playgroud)

只需将变量设置为除非空之外的任何值即可使上述工作正常进行,尽管[ -n "$var" ]会更短(如果不是那么明显的话)。

一般来说,当脚本将环境变量解释为 true 或 false 时,它​​会将任何值解释为 true (有时使用该值来配置某些选项),否则将 null 值解释为 false。

上面返回!not其第一个参数 len 的布尔值 - 如果参数包含 0 以外的任意数量的字符,则返回 0,否则,如果根本没有字符,则返回 1。基本上,这与您可以使用 执行的测试[ -n "$var" ]相同,但它只是将其包装在一个名为 的小函数中bool()

这通常是标志变量的工作方式。例如:

[ -d "$dir" ] || dir=
Run Code Online (Sandbox Code Playgroud)

脚本的其他部分只需要查找任何值即可$dir衡量其有用性。这在涉及参数替换时也很方便 - 因为参数可以扩展到默认值以填充空或未设置的参数,但否则会扩展到预设值,例如...

for set in yes ''
do echo "${set:-unset or null}"
done
Run Code Online (Sandbox Code Playgroud)

...这会打印...

yes
unset or null
Run Code Online (Sandbox Code Playgroud)

当然,也可以做相反的事情:+,但这只能给你一个预设的默认值或根本不给你任何东西,而上面的表格可以给你一个值或默认值。

因此,关于这三种选择 - 任何一种都可以工作,具体取决于您选择如何实施它。该函数的返回是自测试的,但是,如果该返回因任何原因需要保存,则需要将其放入变量中。这取决于用例 - 是您希望一次评估测试并完成类型的布尔值吗?如果是这样,请执行该功能,否则可能需要其他两个中的任何一个。

  • @wurtel - 这依赖于默认的 `$IFS` - 如果 var 的值可能包含任何类型的用户输入,那么也完全取决于运气。如果该值一开始就不是未知的,则几乎不需要测试它。更安全的是,您可以执行 `if ${var:+":"} false; then` 当使用布尔空值/非空值时。但这很少比 `[ -n "$var" ] &&` 更有用 (2认同)
  • @wurtel - no obsession, it's just important to handle all cases. Unintended behavior is a bug - good code is bug free. `$IFS` is a global modifier - it affects all of the code you write, and, for POSIX shells, can be passed in via the environment. So `IFS=t wurtel.sh` would cause your test to fail in that case. Given a POSIX `sh`, that is, and an `#!/bin/sh` bangline. `bash`, for example, though, ignores `$IFS` in the environment. But a `bash` bangline only limits the usefulness of your code more than it need be because you didn't like the quotes. (2认同)
  • @wurtel - 这是个好主意。但是,用户不遗余力地在执行您编写的代码的环境中做一些奇怪的事情应该是您首先期望的——健壮的代码可以处理它,而有缺陷的代码则不能。 (2认同)