在Yocto中出现"sh: : unknown operand"

8
以下内容在Ubuntu中可行,但在Yocto (Poky)中不行。
root@system:~/# x='abc'
root@system:~/# y=''
root@system:~/# [[ $(echo $x) != '' ]] && echo true
true
root@system:~/# [[ $(echo $y) != '' ]] && echo true
sh: : unknown operand

在Ubuntu中,最后一行返回空值(如预期所示)。有任何想法为什么在Yocto中会产生一个错误?

3
我打赌两个平台上的sh不同,在Yocto上可能没有完全实现。我其实很惊讶sh实现了[[,无论是在Yocto还是其他平台上。 - Eric Renouf
Ubuntu使用dash作为sh,而使用OpenEmbedded构建的映像通常将busybox作为sh。 - Anders
@eric-renouf,你有什么想法吗?考虑到它在Yocto中可以正常工作,问题可能是什么呢? - geotheory
2
我猜问题在于它如何处理“空”参数,只要在!=的每一侧都有一个值,它就会起作用。你可以尝试将命令替换引用加上引号,例如[[ "$(echo $y)" != '' ]]...,看看是否有所帮助。 - Eric Renouf
@EricRenouf,谢谢你的帮助。你想把它作为答案添加吗? - geotheory
2个回答

14

问题似乎在于$(echo $y)被扩展为空字符串,然后[[没有正确处理它。解决方法是对命令替换加上引号:

问题似乎在于$(echo $y)被扩展为空字符串,然后[[没有正确处理它。解决方法是对命令替换加上引号:

[[ "$(echo "$y")" != '' ]] && echo true

尽管使用printf比echo好,所以你可以这样做:

但最好还是使用printf而不是echo,因此您可以这样做:

[[ "$(printf '%s' "$y")" != '' ]] && echo true

以防万一 $y 可能会包含特殊字符,这些字符可能会干扰 echo 或类似函数的输出


11

显然,忙碌的box ash对于[[有一个相当简单的实现。它与[相同,只是期望一个]]而不是]作为最终参数。这错过了[[有用之处的关键: [[应该是一个具有特殊解析的关键字,使用它看起来更漂亮,避免了各种陷阱(同时也会增加一些自己的陷阱)。 我猜他们添加它是为了让更多的bash脚本在忙碌的box ash上运行不需要修改。

为避免混淆,我建议在busybox中根本不要使用[[。使用[并引用所有命令替换和参数扩展。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接