【问题标题】:test fails with "argument expected" when comparing "("比较“(”时,测试因“预期参数”而失败
【发布时间】:2009-08-19 10:11:28
【问题描述】:

谁能解释一下为什么这个命令会返回错误(在 Solaris ksh 上):

if [ "(" = "(" ]; then echo 1;fi;
ksh: test: argument expected

同样使用 bash 是可以的,如预期的那样回显“1”
另外,使用 [[ ]] 也可以。

问题好像是第一个"("

【问题讨论】:

  • 遗憾的是,该代码适用于我的 ksh。
  • 有趣,也许这是我的 ksh (Solaris 10) 中的一个错误
  • 以上代码在OSX自带的ksh上运行良好

标签: ksh


【解决方案1】:

该命令似乎对我的 ksh 有效。

但是,在 ksh 中的 IIRC 建议使用 [[ ]] 而不是 []。所以对于一个便携的解决方案,我建议你写成:

if [[ "(" = "(" ]]; then echo 1; fi;

但请注意,[[]] 与 [] 略有不同,因为没有进行通配符扩展。见http://www.bolthole.com/solaris/ksh-builtins.html#test

更新

为了更好地移植到不同的 shell,我倾向于使用内置的 test 命令,它在 ksh 中应该具有与 [[]] 完全相同的效果。

if test "(" = "("; then echo 1; fi

【讨论】:

  • 我通常尽量不使用 [[ ]],因为它不是可移植的(无论如何,对于 bash)
  • 哎呀,我的错。无论如何不要sh
【解决方案2】:

如果将双引号更改为单引号是否有效 - 即,

if [ '(' = '(' ]; then echo 1;fi;

编辑添加:我刚刚能够用 Digital UNIX ksh 重现问题。单引号在这个平台上也不起作用,但是转义括号确实起作用:

if [ '\(' = '\(' ]; then echo 1;fi;

根据 ksh 的手册页,它指出:

以下字符有一个 外壳和原因的特殊含义 一个词的终止,除非 引用:

   ; & ( ) | ^ < > <newline> <space> <tab>

...并继续定义更多的解析规则。即使在引用时(奇怪地),似乎 ( 也被解释为特殊字符,因此需要转义。如果在尝试 if 之前在命令行中键入“set -x”,您将确切看到shell 正在尝试发送到 stderr,前面有一个“+”号,这可能有助于跟踪;例如:

$ set -x
$ if [ '(' = '(' ]; then echo 1;fi;
+ [ ( = ( ]
ksh: test: argument expected
$
$ if [ '\(' = '\(' ]; then echo 1;fi;
+ [ \( = \( ]
+ echo 1
1
$

它可能也取决于 ksh 实现——例如,ksh-88 与 ksh-93 及更高版本。在 Digital UNIX 上,实现是 ksh-88。

【讨论】:

  • 谢谢 - 至少我不会发疯,其他人看到了问题。我无法逃脱它,因为使用的实际代码在文件读取循环中,并且使用了一个变量。即如果 [ "$var" = "test" ]
  • Joe -- 我刚刚尝试过这样做: [ '\'"$var" = '\(' ] ... 这似乎有效。如果我删除前面的 '\' "$var" 它按预期倒下。现在我不知道您实例中 $var 的内容是什么,但是您也许可以根据此提出解决方案?
  • 好的,谢谢 - var 的内容是 "(",这就是问题所在。我打算使用 [[ ]] 解决方案 - 可能不会让未来的维护者感到困惑。
猜你喜欢
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多