新手学习Bash - 不断收到“非法选项”错误

8

我是一个新手,对ubuntu和bash脚本不太熟悉,想知道在使用GETOPTS时为什么会出现错误。

这里是我用来运行它的代码。

sh /home/ubuntu/Desktop/test.sh -f /home/u/Desktop/ -p 'TEST'

我认为我正确地调用了脚本,并且它应该使用grep搜索我输入的术语作为搜索项。但是由于某种原因它没有成功。如果在使用grep时需要一些一般性建议,也请提供,谢谢。

#!/bin/bash

valid=0
file_arg=""
display_help=""
column=""
pattern=""

while getopts f:d:s:m: opt
do
    case "$opt" in
        d)  display_help=$OPTARG
            ;;
        f)  file_arg=$OPTARG
            ;;
        c)  column=$OPTARG
            ;;
        p)  pattern=$OPTARG
            ;;
        *)  valid=1
            break
            ;;
    esac
done

if [ $valid -eq "0" ]
then
    if [ $pattern != "" ]
    then
        cat $file_arg | grep $pattern
    else
        cat $file
    fi
else
    echo -n "Usage: FILE -f <name> | COLUMN -> -c <name> | HELP -> -d | PATTERN -> -p <expression>"
fi
3个回答

17
getopts中,您没有指定p选项,您只有f:d:s:m:选项。我认为您想说的是 p 而不是 m,或者反之。应该是f:d:s:m:p:f:d:s:p:

10

您还应考虑getopts的错误抑制和错误处理功能。

如果选项字符串的第一个字符是冒号(:),则getopts将不会报告错误,而是提供一种自己处理错误的方法。然后可以在您的case条件处理中使用另外两个字符:

  • ? 如果输入了无效选项,则$opt将被设置为?$OPTARG将保留无效字符,例如如果使用了-z,这不在您的选项字符串中,则$OPTARG将设置为z

  • : 如果用户省略了必需的附加参数,则$opt将被设置为:$OPTARG将保留命令字符,例如如果使用-p而不是-p arg,则$OPTARG将设置为p

如果实现了这一点,则*的catch-all变得多余,并且应将其删除。注意:如果您将其保留,并且它位于?:之上,则会出现问题。还要确保?以这种方式转义:\?)

希望这可以帮助您。

# Note the addition of the inital colon before 'f'.
while getopts :f:d:c:p: opt;
do
    case $opt in
        d)  display_help=$OPTARG
            ;;
        f)  file_arg=$OPTARG
            ;;
        c)  column=$OPTARG
            ;;
        p)  pattern=$OPTARG
            ;;

        # Option error handling.

        \?) valid=0
            echo "An invalid option has been entered: $OPTARG"
            ;;

        :)  valid=0
            echo "The additional argument for option $OPTARG was omitted."
            ;;

        # This is now redundant:
        # *)  valid=0
        #     break
        #     ;;
    esac
done

1
如果 ? 没有进行转义,则它可以匹配任何内容,这样就永远无法进入 : 的情况,因此缺少参数会被报告为无效选项。 - Mark Booth
感谢说明,马克。知识很有用。 - mattst

2

你的脚本还有一些问题,正如Jayesh所提到的,你需要包含getopt的所有参数,但你也需要小心字符串比较,这里是几个修复建议:

(参见http://www.tldp.org/LDP/abs/html/comparison-ops.html了解字符串比较信息)

#!/bin/bash

# switch around valid, convention is 1 == true and 0 == false
valid=1
file_arg=""
display_help=""
column=""
pattern=""

# getopt patterns need to match following case statement
while getopts f:d:c:p: opt;
do
    case $opt in
        d)  display_help=$OPTARG
            ;;
        f)  file_arg=$OPTARG
            ;;
        c)  column=$OPTARG
            ;;
        p)  pattern=$OPTARG
            ;;
        *)  valid=0
            break
            ;;
    esac
done

# changed value to reflect true false convention
if [ "$valid" -eq "1" ]
then
    # string comparison in bash should be done using specific operators
    if [ -n "$pattern" ]
    then
        cat $file_arg | grep $pattern
    else
        # typo, this should be file_arg?
        cat $file_arg
    fi
else
    echo -n "Usage: FILE -f <name> | COLUMN -> -c <name> | HELP -> -d | PATTERN -> -p <expression>"
fi

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