如何使用Bash编写命令行工具

6
我希望能够编写一个类似于git的命令行工具,符合POSIX标准。它将接受诸如--help或-h、--version等选项。但我不知道该如何实现。有人可以告诉我如何使用bash脚本来完成吗?请帮帮我,这对我来说是非常新的事情。
例如:如果我的工具名称为Check-code,那么我想要像这样使用该工具;
Check-code --help 

或者
Check-code --version

1
https://dev59.com/dmncs4cB2Jgan1zn5D96?rq=1 - Markus Mikkolainen
3个回答

7
据我所知,“长选项”诸如--help--version不是POSIX标准,而是GNU标准。对于命令行实用程序,POSIX标准规定:

由连字符和单个字母或数字组成的参数,例如'a',通常称为“选项”(或在历史上被称为“标志”)。

为了支持POSIX短选项,值得了解getopts(网上有教程),但它不支持GNU长选项。

对于长选项,你需要自己编写代码来实现。

filename=default
while (( $# > 0 ))
do
    opt="$1"
    shift

    case $opt in
    --help)
        helpfunc
        exit 0
        ;;
    --version)
        echo "$0 version $version"
        exit 0
        ;;
    --file)  # Example with an operand
        filename="$1"
        shift
        ;;
    --*)
        echo "Invalid option: '$opt'" >&2
        exit 1
        ;;
    *)
        # end of long options
        break;
        ;;
   esac

done

我认为这可以是实现长选项的方法之一。使用getopt,我们可以使其简短且适用于短选项和长选项。 - user1497818
非常困难,我看不出如何使用getopts与长选项。你最好使用Perl和Getopt::Long http://perldoc.perl.org/Getopt/Long.html - cdarke
1
你可以在条件语句中检测到单个破折号,并将$opt和$1(如果有选项的参数)传递给getopts进行处理。唯一的优势是能够处理作为组传递的多个单字母选项(例如-ine == -i -n -e)。我从未有人要求过我编写的任何工具具备这种功能,因此我从未费心支持它。 - William
对于长/短,只需使用 |,例如 version|-v|--version) - Adam K Dean

3
你可以使用内置的 'getopts',像这样:
#!/bin/bash

# Parse arguments
usage() {
    echo "Usage: $0 [-h] [-v] [-f FILE]"
    echo "  -h  Help. Display this message and quit.
    echo "  -v  Version. Print version number and quit.
    echo "  -f  Specify configuration file FILE."
    exit
}

optspec="hvf:"
while getopts "$optspec" optchar
do
    case "${optchar}" in
        h)
            usage
            ;;
        v)
            version
            ;;
        f)
            file=${OPTARG}
            ;;
        *)
            usage
            ;;
    esac
done

这仅适用于单个字符选项,而不适用于像-help--help这样的长选项。实际上,我从来没有发现这是一个重要的限制;任何需要长选项的复杂脚本都可能是我会使用另一种语言编写的。


0

可能有更好的方法,但这是我发现有用的方式: 在BASH中,每个参数都由一个变量表示。第一个参数是$1,第二个是$2,以此类推。使用第一个参数匹配选项字符串,如果匹配,则相应地运行一些代码。

示例:

#!/bin/bash
if [ $1 == "--hello" ] 
    then
        echo "Hello"
    else
        echo "Goodbye"
fi

如果您使用C或C++进行编码,则可以使用**argv变量。 **argv是一个双指针,它保存了传递给程序的所有参数列表(其中argv[0]是程序名称)。

谢谢您的回复。我认为我们可以使用bash命令“getopt”。您能否提出使用该命令的解决方案?但我不知道它是否适用于“-h”和“--help”这两种格式。 - user1497818
如果使用 Bourne shell 风格的 test ([),应该引用 "$1"。使用 [[ 不需要在变量周围加引号(但仍需要在包含空格的文字字面值周围加引号)。 - cdarke

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