Bash脚本错误[:!=:预期为一元运算符


95

在我的脚本中,我尝试对第一个也是唯一的参数是否等于-v进行错误检查,但这是可选参数。我使用if语句,但始终收到一元运算符预期的错误。

这是代码:

if [ $1 != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

编辑:

我应该更具体一些:上面脚本的这一部分正在检查可选参数,然后,如果未输入该参数,则它将运行程序的其余部分。

#!/bin/bash

if [ "$#" -gt "1" ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" = -v ]; then
   echo "`ps -ef | grep -v '\['`"
else
   echo "`ps -ef | grep '\[' | grep root`"
fi

...顺便说一句,我想你想要echo "usage: $0 [-v]"$-显示活动的shell选项标志,而不是当前脚本的名称。
查尔斯·达菲

我的那部分正确,我希望它显示当前脚本的名称。
user3380240 2014年

4
欢迎来到stackoverflow,尤其是bash标签!请查看标签Wiki中有用的工具和资源,例如shellcheck,它会指出(尽管并不总是能解释)许多类似问题。
另一个人

@ user3380240,$-不是当前脚本的名称。$0是。
Charles Duffy 2014年

对不起,那是一个错字。
user3380240 2014年

Answers:


186

行情!

if [ "$1" != -v ]; then

否则,当$1完全为空时,您的测试将变为:

[ != -v ]

代替

[ "" != -v ]

...而且!=不是一元运算符(也就是说,该运算符只能接受一个参数)。


8
或者,如果您不担心可移植性,则可以使用双括号,括号内不需要引号: if [[ $1 != -v ]]; then
Mike Holt 2014年

@MikeHolt,的确是这样-我在上述问题的评论中提到了这一点。
Charles Duffy 2014年

@DanielDinnyes,如果为IFS=1,则[ $# -eq 1 ]表现不会很好,而[ "$#" -eq 1 ]即使如此,其表现也仍然符合预期。当然,这是一个病态的案例,但是最好编写在选择时没有'em的软件。
查尔斯·达菲

-2

或者说是看似猖over的矫kill过正,但实际上却很简单……几乎涵盖了您的所有情况,没有空​​字符串或一元问题。

在第一个arg是'-v'的情况下,然后执行您的条件ps -ef,否则在所有其他情况下抛出用法。

#!/bin/sh
case $1 in
  '-v') if [ "$1" = -v ]; then
         echo "`ps -ef | grep -v '\['`"
        else
         echo "`ps -ef | grep '\[' | grep root`"
        fi;;
     *) echo "usage: $0 [-v]"
        exit 1;; #It is good practice to throw a code, hence allowing $? check
esac

如果不在乎'-v'arg的位置,则只需将大小写放在循环中即可。这将允许遍历所有args并在任何地方找到“ -v”(只要它存在)。这意味着命令行参数顺序并不重要。如前所述,如前所述,变量arg_match被设置,因此它仅仅是一个标志。它允许多次出现“ -v” arg。可以很容易地忽略所有其他出现的“ -v”。

#!/bin/sh

usage ()
 {
  echo "usage: $0 [-v]"
  exit 1
 }

unset arg_match

for arg in $*
 do
  case $arg in
    '-v') if [ "$arg" = -v ]; then
           echo "`ps -ef | grep -v '\['`"
          else
           echo "`ps -ef | grep '\[' | grep root`"
          fi
          arg_match=1;; # this is set, but could increment.
       *) ;;
  esac
done

if [ ! $arg_match ]
 then
  usage
fi

但是,允许多次出现参数很方便在以下情况下使用:

$ adduser -u:sam -s -f -u:bob -trace -verbose

我们不在乎参数的顺序,甚至允许多个-u参数。是的,允许以下操作很简单:

$ adduser -u sam -s -f -u bob -trace -verbose

$*在这种情况下不应使用:它将项目连接成字符串,该字符串既是字符串拆分的又是glob扩展的;与有所不同"$@",会留下精确的原始值。而且您缺少一些shellcheck.net将捕获的引号(带有链接到描述这些引号为何重要的Wiki页面的警告)。
查尔斯·达菲,

作为一个具体示例,请考虑-U'Bob Barker'for arg in $*将其视为-UBob,然后Barker视为单独的项目;而for item in "$@"-UBob Barker视为单个字符串。
查尔斯·达菲,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.