Shell脚本参数是否存在

4

I have a shell script, where sometimes user gives the required arg sometimes they forget. So I needed someway in which if the user has already provided the particular argument then the user should not be prompted for that particular arg. Can anyone help?

Example script:

#!/bin/sh
if [ $GAME =="" ]
then
    echo Enter path to GAME:
    read GAME
else
    echo $GAME
fi

Example O/P 1:

$ ./sd.sh -GAME asdasd
Enter path to GAME:
?asd

Example O/P 2:

$ ./sd.sh
Enter path to GAME:
asd


2
据我所知,Shell脚本在没有额外工作解析它们时无法理解命名参数。 当您检查$GAME时,实际上是在检查环境变量,而不是您的参数。 - cHao
@cHao:假设我想检查第三个参数是否存在,它有一个特定的名称,例如:run.sh -name Abhishek -game COD -type Action。如果用户有时忘记了 type,那么应该提示他/她,否则如果他已经提供了它作为参数,那么就不应该提示他/她。 - AabinGunz
第三个参数($3)应该是“-game”。除非将这些参数传递给类似于 getopt 的例程,否则参数名称没有任何意义。如果您要通过参数编号进行检查,那么最好摆脱开关 - 它们在代码方面没有任何作用,并且会误导参数顺序不重要。 - cHao
@cHao:我使用这些开关,因为它们是在此脚本内运行的Java参数,所以我需要它们。请建议其他方法。谢谢。 - AabinGunz
1
看我的回答。有一个getopts命令专门用于处理命名参数。(也有一个getopt,但它有一些怪癖--例如,它通常不能很好地处理带有空格的参数。) - cHao
5个回答

8
if [ -z "$1" ]; then
    echo "usage: $0 directory"
    exit
fi

这里的-z是什么意思?因为如果我使用-GAME,会出现“./sd.sh:test:需要参数”的错误。 - AabinGunz
1
@Abhishek:它检查第一个参数的长度是否为零。 - matcheek
test(1) 的这个参数解析错误是 [ x"$1" = x ] 短语的原因,它可以防止 "$1" 被解释为 test 命令的选项。 - msw
这也可能是由于缺少空格导致的。括号必须被空格包围,因此您不能写成:if [-z "$1"]。这是因为[是一个普通的shell命令,它检查其最后一个参数是否为]。它不是shell内置的一些特殊语法。 - Roland Illig

5

您可以使用$#检查第一个参数。

if [ $# -ne 1 ];then
    read -p "Enter game" GAME
else
    GAME="$1"
fi

$# 表示参数的数量。这个脚本检查参数的数量是否为1。如果你想检查第五个参数,那么使用 $5。如果你真的想要更可靠的东西,可以选择使用 getopts。或者使用支持长选项的 GNU getopt


我该如何引用第5个参数?$#指的是第1个参数。 - AabinGunz
1
@Abhishek $#表示参数数量。$1指的是特定参数的值,在本例中为第一个参数。 - Summer_More_More_Tea

2
如果你想使用命名参数,请查看getopts。它是用于按名称提取参数的工具。该链接还提供了如何使用它的示例。

1
#!/bin/sh
game=""
usage="usage: $0 -g game"
while getopts ":hg:" option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    g) game="$OPTARG"
       ;;
    ?) echo "illegal option: $OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
[ -z "$game" ] && read -p "enter game: " game

嘿,谢谢你的信息,我成功地做到了一个而不使用OPTGET。 - AabinGunz

0

这是我的shell脚本版本,它不使用getopts来解决问题。我遇到的问题是要给命名参数 -GAME 而不仅仅是 -g(即单个字符)。

注意:这里的 -user 和 -pass 参数是为了Java而存在的,因此如果它们没有被提供,我不需要让sh脚本去询问,Java自己会处理。

#!/bin/sh
game=0
if [ $# -ge 1 ];then
 if [ ${6} = "-GAME" ];then
  game=1
 fi
 if [ $game -ne 1 ];then
  echo "请输入GAME位置"
  read GAME
 else
  GAME=${7}
 fi
 echo "游戏:" $1 ",游戏位置:" $GAME
else
 echo "用法:./run.sh gamename"
 echo "用法:./run.sh gamename [-user] [username] [-pass] [password] [-GAME] [path]"
fi
输出1:

./run.sh COD4 -user abhishek -pass hereiam -GAME /home/games
游戏:COD4,游戏位置:/home/games

输出2:

./run.sh COD4
./run.sh: 第4行:[: =:需要一元运算符
输入游戏位置的路径
/home/mygames
游戏:COD4,游戏位置:/home/mygames

感谢大家的努力 :)


唯一的问题在于第二个输出,其中我得到了 ./run.sh: line 4: [: =: unary operator expected,否则它完美地工作。 - AabinGunz
1
在右括号前加一个空格。 - Roland Illig

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