如果下面应该返回 true,但它实际上失败,并在 bash shell 中执行时报告参数过多的错误。我想我遵循了所有带双引号的准则,但无法弄清楚为什么它在我的生活中失败了......有什么想法吗?
#!/usr/bin/bash
# These are the values in the environment
#echo ">"$PS_APP_HOME"<" => >/app/psoft/app_85909<
#echo ">"PS_CUST_HOME"<" => >/app/psoft/cust_85909<
#echo ">"$(pwd)"<" => >/app/psoft/app_85909<
if [ "$(pwd)" != "$PS_APP_HOME" ] -o [ "$(pwd)" != "$PS_CUST_HOME" ]
答案1
[ "$(pwd)" != "$PS_APP_HOME" ] -o [ "$(pwd)" != "$PS_CUST_HOME" ]
[
使用以下参数调用命令:
- 输出
pwd
1, !=
,- 变量的内容
PS_APP_HOME
, ]
,-o
,[
,- 另一个调用的输出
pwd
, !=
,- 变量的内容
PS_CUST_HOME
,以及 ]
。
本来]
是最后一个参数,所以当[
看到-o
第一个参数之后]
,它会感到困惑。
[
有一个已弃用的-o
运算符或者,但这意味着用作[ some-condition -o some-other-condition ]
.然而,不应使用它,因为它会导致不可靠的测试表达式。
在这里,使用或者也没有道理。当前工作目录不能同时是某项 ( $PS_APP_HOME
) 和其他项 ( ),因此或$PS_CUSTOM_HOME
至少其中之一为真。想必你的意思是"$(pwd)" != "$PS_APP_HOME"
"$(pwd)" != "$PS_CUST_HOME"
和代替或者。所以:
使用标准语法:
if [ "$PWD" != "$PS_APP_HOME" ] && [ "$PWD" != "$PS_CUST_HOME" ]; then echo current directory is neither the APP nor CUST home fi
[
(如果第一个命令成功,我们将运行第二个命令&&
壳(不是[
) 运算符)。类似 Korn 的语法:
if [[ $PWD != "$PS_APP_HOME" && $PWD != "$PS_CUST_HOME" ]]; then echo current directory is neither the APP nor CUST home fi
或者
if [[ ! ($PWD = "$PS_APP_HOME" || $PWD = "$PS_CUST_HOME") ]]; then echo current directory is neither the APP nor CUST home fi
其中
[[...]]
是一个有自己的特殊构造条件表达式微语言代码里面也有一些&&
(与)/||
(或),!
(非)布尔运算符。
虽然你也可以使用case
:
case $PWD in
("$PS_APP_HOME" | "$PS_CUST_HOME") ;;
(*) echo current directory is neither the APP nor CUST home
esac
$PWD
类似$(pwd)
,只是它更高效,因为它不需要分叉另一个进程并通过管道获取其输出,并且意味着如果当前工作目录的路径以换行符结尾,它仍然可以工作。²
请注意,上面的双引号很重要,我只将它们放在绝对必要的位置(以防止在构造的/运算符的参数中出现 split+glob[
并防止变量值被视为参数中的模式或),虽然有!=
=
[[...]]
case
全部引用的扩展不会造成损害。
除了进行词法比较之外,还要注意 ksh/bash/zsh[[....]]
和大多数[
实现(包括[
内置的bash
支持运算符)来-ef
检查两个文件是否相同(在符号链接解析之后),因此您可以使用它而不是=
:
if [[ ! (. -ef $PS_APP_HOME || . -ef $PS_CUST_HOME) ]]; then
echo current directory is neither the APP nor CUST home
fi
或者对于sh
(大多数sh
):
if [ ! . -ef "$PS_APP_HOME" ] && [ ! . -ef "$PS_CUST_HOME" ]; then
echo current directory is neither the APP nor CUST home
fi
这里也使用.
它不同于$PWD
或$(pwd)
保证引用当前工作目录。
这样,如果$PWD
是/opt/app
或/some/link/to/app
并且$PS_APP_HOME
是/opt/./app
或/opt/foo/../app
或/opt//app
例如,那仍然有效。
¹ 删除所有尾随换行符,因此可能不是当前工作目录。
² 在某些 shell 中,$PWD
如果当前工作目录已在您脚下重命名,则可能会给您提供过时的信息。但话又说回来,在某些 shell 中也是如此,它们只输出/ /pwd
的值$PWD
并且仅更新它。cd
pushd
popd
答案2
if [ "$(pwd)" != "$PS_APP_HOME" ] -o [ "$(pwd)" != "$PS_CUST_HOME" ]
这在语法上是不正确的,这就是您收到报告的错误的原因。
如果您想将其作为一项测试来执行,则应该是:
if [ "$(pwd)" != "$PS_APP_HOME" -o "$(pwd)" != "$PS_CUST_HOME" ]
或者,如果您想让表达式完全分开并bash
为您处理逻辑“或”:
if [ "$(pwd)" != "$PS_APP_HOME" ] || [ "$(pwd)" != "$PS_CUST_HOME" ]