2010-04-15 309 views
18

关于这类事情有很多问题,但让我们想象我们的目标是安装getopt和getopts的通用Linux系统(并非我们会使用,但它们似乎很受欢迎)Shell脚本参数解析

如何解析两个长(--example | --example简单的选项)和短argruments(-e | -esimple,例如| -e简单的例子)

回答

33

你想用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 \ 
-- "[email protected]")                

# 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。然而,你不太可能会遇到它的需求。

最后,解析选项后,你可以再次致电:

eval set -- "[email protected]" 

这将参数指针移动到任何命令行上留下其他的getopt做解析选项之后。你可以只是shift继续阅读。例如,如果一个命令是这样的:

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

不要忘了做一个方便-h/--help选择打印您的新奇特的选择,一旦你就大功告成了。 :)如果你输出help2man友好,你有一个即时手册页去你的新工具。

编辑

在大多数发行版,你可以找到更多的例子/usr/share/doc/util-linux/examplesgetopt代码,它应该已经默认安装。

+0

我知道我在这里没有理智地检查多个命令设置MODE。在这种情况下,可以接受的是最后一个选项简单地优先,并且该粘贴仅仅意味着关于使用'getopt'的一种方式的信息。 – 2010-04-15 07:55:20

+0

我已经多次提到过使用'getopt()'。叫我愚蠢,但我不明白它是如何工作的。由于我的脚本需要一个窗口等效,我[使用此](http://stackoverflow.com/a/3981086/314056)。在我看来,这是一个更清洁,不太神奇的方法。我可以在Linux上做类似的事吗? – Christian 2012-10-21 09:46:35

+0

@Christian你可以和BASH类似,'%1'变成'$ 1'(如果'$ 1'需要参数则分别为'$ 2')。事实上,许多人只是这样做,通过'shift'循环参数并通过开关运行当前参数。'getopt'只是处理所有这些魔法,加上强制性的参数检查,这么多方便。 – 2012-10-21 11:21:49