Bash:test(内置)和几个参数:它们是如何解析的?
我没有为bash内置的Bash:test(内置)和几个参数:它们是如何解析的?,bash,shell,test-command,Bash,Shell,Test Command,我没有为bash内置的测试/[命令使用这个特定的构造,但是今天我遇到了它,我感到困惑。它看起来像这样: [ -n "${FOO}" -a -r ${FOO}/bar ] && echo OK [ -n "${FOO}" ] && [ -a -r ${FOO}/bar ] && echo OK 我知道每个开关各自做什么,但我不确定它们按这种方式分组时的行为。特别是-a-r[operant]部分。下面是man页面必须说明的内容: 使用一组基于参数数
测试/[
命令使用这个特定的构造,但是今天我遇到了它,我感到困惑。它看起来像这样:
[ -n "${FOO}" -a -r ${FOO}/bar ] && echo OK
[ -n "${FOO}" ] && [ -a -r ${FOO}/bar ] && echo OK
我知道每个开关各自做什么,但我不确定它们按这种方式分组时的行为。特别是-a-r[operant]
部分。下面是man
页面必须说明的内容:
使用一组基于参数数量的规则测试并[计算]条件表达式
0个参数
表达式为false。
1个参数
当且仅当参数不为null时,表达式才为true。
2个参数
如果第一个参数为!,则当且仅当第二个参数为null时,表达式才为true。如果第一个参数是列出的一元条件运算符之一
在上面的条件表达式下,如果一元测试为true,则表达式为true。如果第一个参数不是有效的一元条件运算符,则表达式为true
为假。
3个参数
以下条件按列出的顺序应用。如果第二个参数是上面条件表达式下列出的二进制条件运算符之一,
表达式的结果是使用第一个和第三个参数作为操作数的二进制测试的结果,-a和-o运算符被视为二进制运算符
当有三个参数时。如果第一个参数是!,则该值是使用第二个和第三个参数对两个参数测试的求反。如果第一个参数
参数正好是(第三个参数正好是),结果是第二个参数的一个参数测试。否则,表达式为false。
4个参数
如果第一个参数是!,则结果是由其余参数组成的三个参数表达式的求反。否则,将解析表达式并
使用上面列出的规则根据优先级进行评估。
5个或更多参数
使用上面列出的规则,根据优先级解析和计算表达式
好的,很好。由于我提供了5个参数,表达式将被解析并应用规则。我假设它将被拆分并分为两部分进行计算,如下所示:
[ -n "${FOO}" -a -r ${FOO}/bar ] && echo OK
[ -n "${FOO}" ] && [ -a -r ${FOO}/bar ] && echo OK
但事实并非如此,因为这会产生所需的[:-r:binary operator
,它不像[-a-r…]
。当然,这是可行的:
[ -n "${FOO}" ] && [ -a ${FOO}/bar ] && [ -r ${FOO}/bar ] && echo OK
这也是:
[ -n "${FOO}" -a ${FOO}/bar ] && echo OK
但这失败了:
[ -n "${FOO}" -r ${FOO}/bar ] && echo OK
让我更加困惑的是,有一部分说:
当有三个参数时,-a和-o运算符被视为二进制运算符
-a
作为一个二进制运算符到底是如何处理的?我相信它测试文件的存在性,但它在这里是否有其他行为?它与第二个操作数有什么关系?Bash内置如何测试
解析原始示例中的参数?我缺少什么?您不需要在u解析它,因为&&
取代了它
[ -n "${FOO}" ] && [ -r ${FOO}/bar ] && echo OK
听命于你
test -n "${FOO}" -r ${FOO}/bar
-n "${FOO}" -a ${FOO}/bar
你们有两个条件,但你们不能告诉测试两者是否都需要为真,或者一个条件为真是否足够,这就是为什么你们会得到一个错误
test -n "${FOO}" -a -r ${FOO}/bar
test -n "${FOO}" -o -r ${FOO}/bar
听命于你
test -n "${FOO}" -r ${FOO}/bar
-n "${FOO}" -a ${FOO}/bar
你也有两个条件,但在这里你清楚地说(使用-a
)这两个条件都必须是真的。因此这是可以的。其他答案都是正确的,但我将添加我自己的,以便直接解决最初导致我困惑的原因
这适用于Bash内置,也适用于BSD/bin/test(对示例稍作修改)
测试
/[
(我将使用测试
来指代两者)命令实现的语法本质上是不明确的:它将接受开关-a
和-o
,但它们的含义取决于上下文。当作为两个布尔操作数之间的连接符应用时,-a
充当逻辑和。但当用作一元运算符时,它检查是否存在t文件名在下一个参数中给出。类似地,-o
被视为逻辑或,也被视为是否启用shell选项的测试
这为一些奇怪的表达打开了大门。正如@user1934428在回答下面的评论中所讨论的,有以下内容:
#假设${FOO}/bar存在,那么它是可读的:
[-n“${FOO}”-a-r“${FOO}”/bar]
#与以下任一项完全相同:
[-n“${FOO}”-a-a“${FOO}”/bar]
[-n“${FOO}”]&&&[-a“${FOO}”/bar]
也许这看起来很琐碎?也许你渴望困惑?我甚至不打算尝试破译这些:
#假设${FOO}/bar存在且可读,则返回1:
[-n“${FOO}”-a-a-a-a“${FOO}”/bar]
#这将返回0:
[-n“${FOO}”-a-a-a-o-o-o“${FOO}”/bar]
我对此的理解很简单:在使用test
时,坚持使用基本的、明确的构造。不要戳一只睡熊。在本文中被解释为“and”,应用于两个操作数-n“${FOO}”
和-r${FOO}/bar
?这几乎太简单了,我专注于它的一元用法来测试一个文件是否存在…-a
是和,-o
是或和不是!
不是我有一些极端的隧道视觉。-a
以上下文相关的方式表示两种不同的东西,这让我非常沮丧。假设如果${>{FOO}/条形码
存在,那么它也是可读的:[-n“${FOO}”-a-r${FOO}/bar]
将与[-n]完全相同