Shell 脚本参数解析

Posted

技术标签:

【中文标题】Shell 脚本参数解析【英文标题】:Shell script argument parsing 【发布时间】:2011-02-08 05:16:54 【问题描述】:

关于这类事情有很多问题,但假设我们的目标是安装了 getopt 和 getopts 的通用 Linux 系统(我们也不会使用,但它们似乎很受欢迎)

如何解析长参数(--example | --example simple-option)和短参数(-e | -esimple-example | -e simple-example)

【问题讨论】:

【参考方案1】:

您想将getopt 与多头和空头选项一起使用。工作代码示例:

# Parse arguments
TEMP=$(getopt -n $PROGRAM_NAME -o p:P:cCkhnvVS \
--long domain-password:,pop3-password:\         
,create,cron,kill,help,no-sync-passwords,version,verbose,skip-pop3 \
-- "$@")                                                            

# Die if they fat finger arguments, this program will be run as root
[ $? = 0 ] || die "Error parsing arguments. Try $PROGRAM_NAME --help"       

eval set -- "$TEMP"
while true; do     
        case $1 in 
                -c|--create)
                        MODE="CREATE"; shift; continue
                ;;                                    
                -C|--cron)                            
                        MODE="CRON"; shift; continue  
                ;;                                    
                -k|--kill)                            
                        MODE="KILL"; shift; continue  
                ;;                                    
                -h|--help)                            
                        usage                         
                        exit 0                        
                ;;                                    
                -n|--no-sync-passwords)               
                        SYNC_VHOST=0; shift; continue 
                ;;                                    
                -p|--domain-password)                 
                        DOMAIN_PASS="$2"; shift; shift; continue
                ;;                                              
                -P|--pop3-password)                             
                        POP3_PASS="$2"; shift; shift; continue  
                ;;                                              
                -v|--version)                                   
                        printf "%s, version %s\n" "$PROGRAM_NAME" "$PROGRAM_VERSION"
                        exit 0                                                      
                ;;                                                                  
                -v|--verbose)                                                       
                        VERBOSE=1; shift; continue                                  
                ;;                                                                  
                -S|--skip-pop3)                                                     
                        SKIP_POP=1; shift; continue                                 
                ;;                                                                  
                --)                                                                 
                        # no more arguments to parse                                
                        break                                                       
                ;;                                                                  
                *)                                                                  
                        printf "Unknown option %s\n" "$1"                           
                        exit 1                                                      
                ;;                                                                  
        esac                                                                        
done     

注意,die 是之前定义的函数(未显示)。

-n 选项告诉 getopt 将错误报告为我的程序名称,而不是 getopt-o 定义了一个短选项列表(: 在选项之后表示需要的参数),--long 指定长选项列表(对应于短选项)。

剩下的只是一个简单的开关,适当地调用shift来推进参数指针。请注意,拨打shift; shift; 只是一个顽固的习惯。在当前的现代世界中,shift 2 可能就足够了。

现代的 getopt 在较新的平台上非常一致,但是您可能会在较旧的(大约 Redhat 9 之前的)系统上遇到一些可移植性问题。有关向后兼容性的信息,请参阅man getopt。但是,您不太可能会遇到对它的需求。

最后,解析完options后,可以再次调用:

eval set -- "$@"

这会将参数指针移动到 getopt 完成解析选项后留在命令行上的任何其他内容。然后你可以shift 继续阅读它们。例如,如果一个命令看起来像这样:

./foo --option bar file1.txt file2.txt file3.txt

完成后,别忘了创建一个方便的-h / --help 选项来打印您的新奇选项。 :) 如果您使该输出 help2man 友好,那么您就有一个即时手册页可以与您的新工具一起使用。

编辑

在大多数发行版中,您可以在 /usr/share/doc/util-linux/examples 中找到更多示例 getopt 代码,默认情况下应该已安装。

【讨论】:

我确实意识到我在这里没有理智地检查设置模式的多个命令。在这种情况下,最后一个选项优先是可以接受的,并且粘贴只是为了提供有关使用 getopt 的一种方式的信息。 我已经多次被提及使用getopt()。叫我笨蛋,但我就是不明白它是如何工作的。由于我的脚本需要一个等效的 Windows,我 used this。在我看来,这是一种更清洁且不那么神奇的方法。我可以在 linux 上做类似的事情吗? @Christian 你可以用 BASH 做类似的事情,%1 变成 $1(如果 $1 需要一个参数,则分别是 $2)。事实上,很多人就是这样做的,通过shift 不断循环参数并通过开关运行当前参数。 getopt 只是处理所有这些魔法,并为您提供强制参数检查,很多人都喜欢这种便利。 谢谢蒂姆。我明白为什么getop 更好,我只是无法在不到 10 分钟的时间内弄清楚它是如何工作的,与简单的 1:1 翻译相比,这对我的任务来说太多了。另外,让两个脚本都遵循相同的代码模式可以更容易维护。无论如何,感谢您对此的洞察力。

以上是关于Shell 脚本参数解析的主要内容,如果未能解决你的问题,请参考以下文章

sh 解析shell脚本参数的简单方法

在 ksh shell 脚本中考虑临时变量后解析参数

sh 解析shell脚本中的选项和参数

shell 脚本参数解析之 getopt getopts

sh 简单的bash shell脚本模板。有两个版本:1)简单的基于env var的选项,以及2)添加了命令行参数解析

spark提交参数解析