bash - 带感叹号的条件表达式仅适用于双括号
问题描述
我有一个安装工具的脚本,如果它不在我的系统上:
#!/bin/bash
ASCIIDOCTOR_BIN=`command -v asciidoctor`
if ! [ -x $ASCIIDOCTOR_BIN ]; then ......
问题是,它似乎不起作用:条件表达式总是计算为false
.
即使
#!/bin/bash
ASCIIDOCTOR_BIN=`command -v asciidoctor`
if ! [ false ]; then ......
事实证明条件是错误的。
当我在玩它时,我发现如果我用双括号替换括号,它会起作用:
#!/bin/bash
ASCIIDOCTOR_BIN=`command -v asciidoctor`
if ! [[ -x $ASCIIDOCTOR_BIN ]]; then ......
任何人都可以解释这是为什么吗?我被告知要避免使用双括号并且好奇,如果有其他方法可以使这个脚本工作。
我正在开发 Ubuntu 20.04。
解决方案
您的问题是您缺少引号,并且不了解参数扩展的工作原理:
假设您输入 bash 提示符,请考虑以下内容:
$ a=""
$ b="helloWorld"
$ bash -c 'for arg; do echo "got arg: $arg"; done' _ $a $b
got arg: helloWorld
您会假设使用位置参数调用 bash:
$0 = _
$1 = "" # empty string
$2 = "helloWorld"
但实际上,参数$a
扩展为空,导致 bash 被调用:
$0 = _
$1 = "helloWorld"
将我们的知识应用于您的示例,您会注意到 if$ASCIIDOCTOR_BIN
为空,即当命令不存在时,if 语句将变为:
if [ -x ]; then ...
它将测试字符串-x
是否为空,显然不是。
解决方案是始终引用参数扩展:
$ a=""
$ b="helloWorld"
$ bash -c 'for arg; do echo "got arg: $arg"; done' _ "$a" "$b"
got arg:
got arg: helloWorld
你应该知道的一件事[
是它不是语言语法的一部分,而是一个命令,通常在 shell 中实现。
true
and也是如此false
,这些也是命令,这意味着[ false ]
只是测试字符串false
是否为空,显然不是。
所以参数扩展等适用于它的所有参数。
上的注释[[
。[[
是一种特殊的 bash 语法,其中参数扩展的工作方式不同,因此您的代码可以工作。
你可以找到一篇关于参数扩展如何在 bash 中工作的很好的文章:https ://mywiki.wooledge.org/BashGuide/Parameters
推荐阅读
- ubuntu - 配置中的VSCode空嵌套引号字符串停止工作
- ios - 以编程方式设置集合视图标题的动态高度的最佳方法?
- android - 错误的第一个论点 tpe。找到 'my.example.muhammadusman.event_App.myregistration' ,需要:android.support.v4.app.Fragment
- sql - 如果行名称重复,则仅返回具有重复名称的行
- python - 文件夹被解释为文件
- java - 装箱值被取消装箱,然后立即重新装箱 - Double
- c# - 在线程中解码连续的数据流而不阻塞接收器
- ionic3 - 在滚动事件上将 scrollTop 传递给离子组件
- ios - UITableView 单元格上的 NSContiguousString 泄漏
- javascript - Google 在 World Cup Pin It Live 工具中使用了哪些 JavaScript、HTML、API?