一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 1773|回复: 9
收起左侧

getopt/getopts:Bash中命令行选项/参数处理

[复制链接]
发表于 2017-2-21 23:15 | 显示全部楼层 |阅读模式

, l- ^) F1 L( H2 \# c' egetopt/getopts:Bash中命令行选项/参数处理
. [5 E3 |9 w" l. d
) A- [, W  }) z5 A$ y0.引言
  T* G- Q7 Y, B9 B0 d  h) u
% Z7 f/ ]: `* c写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
- G! ~0 o: C' d: t
% _# B1 N' w' ?: {+ z" w  o6 z# E7 @选项与参数:
' b  N, i5 t7 y" w" V7 |! {( r6 t% k8 h2 R- X& J! v& c( f
如下一个命令行:
0 @. T5 ~* n0 q" w- y% d# V  U, W* r4 ~
[vb]. ^8 Y) I+ i. ^  s3 n
./test.sh -f config.conf -v --prefix=/home( G) G  l2 ?9 a" K
% F) s; z$ \" M4 z' q1 V
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
% t/ @0 [" Q, T, {# A( K' e+ k& |# d, Y
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。* c9 D/ r% ^' k% Y' M- ^/ |

/ P9 e& o1 U  z! F在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。! L: c  U- L0 ^3 w, d( B6 F" N
- b8 v1 |- _5 D! }# }
手工处理方式2 @$ x+ ]' e1 M
5 h5 L, e! ^& {0 Q3 N* M! B6 Z
getopts4 k" N; e" N& i2 ~+ i; T: \! F" E
3 Q( g. l  B; q/ z8 t
getopt& K% h& R: y" e7 J( M( a

& r$ ?7 H& H( b下面我们依次讨论这三种处理方式。( M$ p0 x- E( e) M/ f! H

! x+ q) J2 w" j/ B0 \+ e5 j1. 手工处理方式
; P' V$ c: @% m$ g8 ^9 b$ g9 t9 s- ]1 T0 t5 s$ ?6 w' ?  [
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:
& a6 ^* B8 I, G' Y( Z) `) L( v
; t5 j2 f9 _8 `0 [3 c$ c& B/ X4 o$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
% O/ E/ _, d5 P$1 : -f,第一个参数.
0 E9 i/ N1 U" Y: x' K9 v
: [4 A4 A( |+ f% n* _$2 : config.conf
7 w& v5 q& s0 [
2 y! p6 _- A. h' m$3, $4 ... :类推。  J; v/ n* K' q

, n/ k3 q; b, B$# 参数的个数,不包括命令本身,上例中$#为4.
  T6 L7 i4 o2 H1 a# m5 b. x8 s% l+ I& W0 |2 B% o0 a
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
9 {+ U8 h. P2 e! x0 f5 `8 {1 O; @4 k2 ~+ H/ R
$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:: \$ f; u5 b! @7 k. \

. {$ ?$ ]+ ?' z! n[vb]
$ [8 Y3 f/ _6 |/ W#!/bin/bash
. q# }' m4 F+ Q" [3 o* F& T: C. k  ]) ?9 ?# X, q' P
for arg in "$*"7 t4 H6 L6 ~* E4 Y: c/ `, C/ L" h
' q4 O3 H0 j, l8 h$ q
do
& W- Q4 g5 q2 n& j8 S# r; m' F) h! B+ R& ?9 ^! A( e7 |, |
echo $arg
6 l6 G+ f5 u! j6 l) b
' e% o  `/ V( M2 r6 X, ddone0 M8 H* o) u# ~( G% n
' D4 k. o8 h, h- V% ?/ K$ k" ]( }: L8 g
for arg in "$@"
# ~# |2 C& J' R$ r: H
( w0 m5 m) r* i) Pdo, p4 `$ v& v9 p. Y. F

6 y' l8 M+ b5 w4 K8 Oecho $arg) g& z7 M/ P4 ^* R; p+ l
: G" F7 X  o; ?5 A  {! x
done8 j3 N5 Q2 l$ v6 y8 [$ x! A* j
0 t8 H3 m! g' ?+ ]
执行./test.sh -f config.conf -n 10 会打印:
, u7 X/ a/ r+ `& r; Q' g7 L( V, Q  E$ L( \3 b0 z9 I3 e/ ?. y" _
-f config.conf -n 10 #这是"$*"的输出2 I+ w2 m. A+ x5 B) Q5 V

  |6 F2 u' d- b$ e. o) ~#以下为$@的输出9 ^: [8 Z6 h9 W. R9 N* D  S  Y6 m
: m! r9 D/ F" D: o
-f0 L) a. s& X! M" H

" u1 N1 l6 c" p5 J4 R( |7 Bconfig.conf
: O" }, s% x* T1 @
. \, L- [" v8 ~-n; N- }5 G& I- K
" |4 i4 @& P/ V# o
10; [; n1 i5 j  N* \3 F3 U. \

+ A  x* X- {9 {  m7 m' k8 a' |所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
5 V! t. b" s* G# G+ _
: e7 C0 [2 ~3 ]" t& X! G“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:# i$ z4 i6 }8 t% `
' v* X/ I* I  N3 o- n
[vb]/ O$ j0 e* k$ o8 ]  i$ L. z
#!/bin/bash
1 N. E8 N" ^3 {" s  U5 R# D" F! w/ ~
#if [ -n "$1" ],参数不为空 . C7 W0 Q9 P& H. T. t6 l/ u; P
if [ "$1" != "" ] 5 `' B4 z5 _4 ?1 O0 n& w4 y
then
0 G: _$ R9 K, o+ C* M# {
6 n  p- _# y/ a/ j8 x# [#...有参数
4 Y% M" W1 K- Z/ a, M, ~' _3 U  U
else
, a% {  E( y3 q% w
, p! m/ O) W" W- i" H# Qthen" K  C( m  Z1 b5 c' Q! x" }3 s5 _

0 i! x* h; Z' J" G: q3 ]/ u#...没有参数
, e: f  Y1 k+ m
, a& N  ~- I7 ]" D  s5 nfi
9 ~2 \! G! C' V; D2 L. s7 X; r3 N$ E8 M9 G( l3 G' L/ s8 B
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。1 |6 d1 H; w% ~  ~, ^' K. I

, }7 i! m1 x8 ]( @8 B2. getopts/getopt3 V1 T* k; H: `$ J6 o+ v
- F! r) G* o* x2 o# V
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:
; m7 ]6 F+ u4 M- t5 r5 `. g2 M: U( q. e! @8 l
./test.sh -a -b -c : 短选项,各选项不需参数* M+ C+ P% Y4 d! n# u$ x) V
) d4 J  ~8 Y" E3 ?7 ?0 \# L: t- ~: [) S
./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
6 n7 ~" k' l0 I: d% N, z/ _1 v% b" Z' Y1 S% n5 l5 G: y8 f0 }5 M
./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。! F% m2 ]! ~, M+ x& g2 f2 ?
1 {  B  }% W6 U4 `; k
./test.sh --a-long=args --b-long :长选项
: }. K; ]# v2 a! [* h# P
) M: i8 M7 M( I! L我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh# m* ?$ H  M/ c" y2 ^, e

# d+ f5 [) r" E) K[vb]4 s) u" t4 u2 E) H7 L
#!/bin/bash
; u+ N, E5 I) K( |2 n5 U7 S8 h
' B0 O7 c  J& t#选项后面的冒号表示该选项需要参数
; h0 Y. m* K) j& j! ]% i' s9 T1 G0 [. e$ n" q) i5 n3 ]
while getopts "a:bc" arg
. _2 C9 @" ]% B  g  c, y5 @' o2 L8 {6 ]4 v. ?1 a) Q
do2 r6 f0 w; S! y

4 E3 ]* m: ^, {9 w6 K, dcase $arg in
1 W8 D' N2 R& C6 |0 U* j: W; w
% _, f2 U& Z: T! {( }a)
- ]0 d% n  S  t, S! s4 q% S- v& w$ C, }* @/ n
#参数存在$OPTARG中) O( }" c4 B3 _8 h. \! X  O% ^3 ?
& P: Q) F/ K- E, M. E
echo "a's arg:$OPTARG" ;;# c2 Y0 W, y6 |; Z) ~5 j$ Q  `$ I4 o

  d7 k" \' x2 d- \; [8 Ob)
0 `  g6 g; Z6 R& j$ x
: q, {! |4 D6 Q# ^& }echo "b" ;;2 G& {0 J% G" O8 \4 a1 ?

6 O% D9 T' m+ |" i3 o6 T6 O" Kc)
9 t- ^' U% }/ {9 R) }4 O: N) n" @# ?$ |' g, k% A
echo "c" ;;
; O9 q0 M* ]$ o" `& g6 h/ K9 J  _5 A* ~7 }! L
?)
/ D" d. H5 c" a  V7 W$ F" y7 w9 n5 ?
#当有不认识的选项的时候arg为?( b, \7 n4 B6 O2 g
- F' ]( d. s- c" k0 n6 a. q
echo "unkonw argument" exit 1 ;;
3 U( |3 r7 j, V- L
1 C9 E" i& l6 U3 v6 y' F5 Wesac
( @( I0 ]/ q2 M# T
( t6 D: H, b1 x4 ^' Odone
2 Q* z# p4 x) s* N' H9 K6 y( B/ D$ I* R' R" r
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
9 g, Z  M3 X1 j/ z4 I. X0 }/ [7 ]7 ?$ f
来加载了。* y( `8 V  X( y+ b8 b
. |  f! `1 }; c# P# B  {2 {. b
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
) K3 n' g. J! l, V7 x* b  V
% H/ {# r7 D5 i+ I[vb]
' Q- F; p# c: u& I1 G( k7 Q#!/bin/bash
& H* C' d* K6 B) S) e) e  ~  ]# S3 v& r( a
# A small example program for using the new getopt(1) program.' d- @" O/ S, q7 A

1 T7 ?* x+ h" w* D# This program will only work with bash(1). T7 R( S+ |: G( d* E; y" |5 X
- @5 U8 P& p& }% Q. F
# An similar program using the tcsh(1) script language can be found
% ]; g. p# \+ @" `! b$ F4 h
/ E, d$ A% Z$ O: m* L. s# as parse.tcsh* {0 ^3 |" ]7 q# n5 r
' ]1 U' D! q/ W2 Q
# Example input and output (from the bash prompt):0 k, @) I3 |7 c9 G' C0 v$ @
: ?+ a8 m+ i  J+ i$ ~5 l: _
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "% h/ b7 n1 O9 X/ w+ L
% c+ H; L: k$ D0 k; D& i4 Y7 O6 e
# Option a: u( e, P1 B  t. }. c3 |, [
# U. B8 T. p/ f6 d3 a6 o3 p
# Option c, no argument
( K9 W! B, N$ g$ a% h6 g. z% ]% l
/ Q$ `) U* @4 j) m5 ^# p$ V# Option c, argument `more'( d1 z" f( A7 V# J5 S

, i) c) _$ f! p. C+ X# Option b, argument ` very long '
0 ]' n  o) a; R  P5 }! f6 e; Z* h& ^: v- B/ P+ V
# Remaining arguments:: n7 E' J( A- c  J3 Y

$ m+ k! w( Z' ^" x* e# --> `par1'/ o7 n; ~. k0 v4 s! n* b4 V
/ `! @- g3 m  t5 _2 S
# --> `another arg'9 [) z6 W8 X; N8 N8 a8 b$ {
% q1 F( _/ w. D  d$ [
# --> `wow!*\?'
4 O2 z+ d- f8 B( y% s; {5 h1 r# A8 v# t/ `
# Note that we use `"$@"' to let each command-line parameter expand to a- h( Z# o& j/ N5 ~( U* G% @# v
4 `6 L. ^* g4 |, h( h5 O. T8 P
# separate word. The quotes around `$@' are essential!9 ^# g2 y# p( Z; z

( n" E6 K. w9 ^# We need TEMP as the `eval set --' would nuke the return value of getopt.
, g3 I# f, D2 p
! C7 K; Z! E: X% H, D0 z/ l" j; t#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
; L+ e! [" l3 H
' d7 R! k8 R  k! ?3 {0 T7 y) s/ B#如-carg 而不能是-c arg
' I5 W6 e/ {' ]4 q& }& l: T
/ g3 u3 q) Q5 H5 a, E#--long表示长选项4 ?7 O' z5 X9 L- M+ e+ ^: |/ F

  q' M) g) x3 B+ O) J#"$@"在上面解释过
' F0 y2 D* c2 ]- Q0 C2 O
" C# o& W& B* }' M/ i# -n:出错时的信息( H9 q/ \9 k5 W' Z& K1 N' H2 l

" J: f, j$ r; g0 d* j5 w( @# -- :举一个例子比较好理解:
9 p' M& _7 [. F* j$ U. V. _
( |: w# T6 r5 b. f& Y$ B6 E#我们要创建一个名字为 "-f"的目录你会怎么办?
; l. X' {* n) W0 Q; X& t, f
( Y$ f3 R  D) O. q/ Q. s) D# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
3 b9 P3 `/ K0 T3 a4 B( [1 c
: f, {7 I) ~4 T# mkdir -- -f 这样-f就不会被作为选项。
! i1 s- m& Y: k: v: Y3 f+ G1 J
) S* L8 x) m5 T$ P$ l7 w  {$ TTEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
! D$ q- M: t2 L" o5 O2 x! ^1 ]& R0 c- _6 C$ |4 z% q
-n 'example.bash' -- "$@"`
$ ^* c! ?7 k* s. u
( o/ ?# i- T0 O" t2 Y1 ?' Kif [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
6 C0 r% C! x$ Y- i# @# Note the quotes around `$TEMP': they are essential!
7 _3 x9 a  D  |( l1 q- ]2 k6 T3 j
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了$ C8 ~% z0 W* q! G' ?

; j8 i- B- H$ O: S* geval set -- "$TEMP"
/ r' B8 p. M- f! B+ u7 L
# t. m2 o4 i3 q: s  _$ l#经过getopt的处理,下面处理具体选项。+ F+ E% x, D% f0 V& s
$ b% S7 e! Z5 a* |# j: u
while true ; do$ n  [8 j4 |; a9 ~9 R1 s

: X, C; Y1 ^  ocase "$1" in
1 T. r4 B. X1 D9 N, G+ ]& {5 P8 V. M' m: E1 E, R$ `; d" T
-a|--a-long) echo "Option a" ; shift ;;
3 g. f3 n, U4 R% v! z
% B! O5 b7 n. c- \-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
8 e7 a( S9 v! J0 m; F) r2 a3 B  J& Q  K2 N% G
-c|--c-long)( w/ {( d6 I& b; U8 v& Y
% P, y( ~$ h8 `( @, I. d" {
# c has an optional argument. As we are in quoted mode,+ C) `- m- G) P3 ]) d& u4 P& V/ h7 c2 k

  P$ Y; e+ l  t% c; m) \' E( P, E# an empty parameter will be generated if its optional2 Q9 B# n  m; u* F% X/ ~" w; Y, v
- |1 X3 k0 x8 V% c
# argument is not found.
) m+ W2 J; e$ Q: H- n0 z
. U" C, S) ^+ r' acase "$2" in# l, t0 s# V! z, ^; E2 J- s

& N! ^  L4 n. L7 N% A"") echo "Option c, no argument"; shift 2 ;;5 {! K5 j! v( M+ J/ `) c
5 t, m  X! q; l
*) echo "Option c, argument \`$2'" ; shift 2 ;;8 ?0 B1 ?- \3 E9 [$ z- j4 d

+ H$ r0 M1 ~$ T8 g8 P7 Zesac ;;; H+ ]9 ?* Q$ s8 l2 r: U
' |6 s& u5 x/ _/ ]& u4 T6 l
--) shift ; break ;;2 g/ O. q& H# j' M

+ Q+ l" M( t# a( Y*) echo "Internal error!" ; exit 1 ;;: r* t% {) J  {% J0 n6 b' H) Y

" j4 H8 w/ p9 f4 s6 V7 |9 Resac
; {8 J% [7 W5 s. I2 `4 e5 N' F- f/ Q8 l$ W8 @& X1 l
done
8 P5 L, e. N; y. K1 h7 S* l% m+ [4 N" I2 N' H
echo "Remaining arguments:"* S  K9 ^  _/ a6 j" u
) }! `, N' T9 H
for arg do
2 y+ l$ p5 d$ h+ N2 ]' E. S; O! J6 b7 S8 e" s8 E' b
echo '--> '"\`$arg'" ;4 }& W3 x* M. x9 r% M

* V/ w" w2 {7 Z( [' }/ adone
) x! D, M9 N& ~  z( E& V# e
% g* O& W9 L" _! \
" I0 ]0 O! Q3 I, D2 m* |比如我们使用
0 d& D9 v/ Y* s0 g0 M
$ c7 A8 V& l! J3 ]& z! I+ X./test -a -b arg arg1 -c( z6 \$ Q: d; Q& d) @2 O) A6 F

9 \; Y. o- H! n' j. A* r3 ^你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
0 `1 C3 V. O! h* a
7 H/ t2 g6 m  Z' b2 s-a -b arg -c -- arg1- I; u" B2 T$ Q8 M  I

3 L. S) y; @) X( j4 E$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
: w; f6 X4 v2 A0 M
/ ~/ ]. l, s: r4 i% N% h  K  Y3. 总结: k6 |/ P' k1 E7 k( a- K& P$ s! b* r

6 `% g' m" M* X4 D豹尾。
8 ~! i) X' |  \" i1 ^8 U7 M! ^1 f9 N5 P4 f# \5 T- O
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
% t$ t; h, Z$ ?
+ G' w# ^  A: H6 [- B- {2 O
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
$ Y( l1 q# }) M6 A( I7 y8 B记得getopt常与shift结合使用,while循环一下就好了。

7 m% q  R+ ]. O/ W6 B请教一个问题
+ h5 O% S' f! |2 d: `有一句 :set -- `getopt -q ab:c "$@"`. V6 z0 c3 f1 ~; l
请问 这个如何解呢??" |' j2 m2 m: s4 l
 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句2 b( i+ ~% W" b- B, e9 @
set -- `getopt -q ab:c "$@"`' m0 v  g) u& X" `' c8 h' O( K
while [ -n "$1" ]
* w1 k& ?  h7 B: q/ a/ Udo
+ R0 T& ^4 I7 j1 E  n2 B  case "$1" in7 T( C: b* \0 N4 v4 S# k6 u2 M
  -a) echo "Fount the -a option";;
& b1 c/ U7 V4 K( B; K. w! m- {! H( t$ N4 b/ J% Z) H1 _/ [
  -b) param="$2"
$ K& G! j$ w4 N2 \1 ^0 I% L      echo "Found the -b option. with parameter value $param"
0 B( B6 e/ m0 a4 ^      shift ;;) j' I% n) D9 q% F1 X

' {& ?: t! w0 ^, Z  -c) echo "Found the -c option";;
, g: d% p! k/ Q) [5 g/ X2 }  e# y
% S, F8 ~1 n- Z9 f3 o) X3 p  --) shift/ T9 e1 G) q( _' U9 I$ _# R
      break;;  L9 g; y$ L$ P- m; x

& I) `7 F) `7 H: ^5 |& p  *) echo "$1 is not an option";;  u: r; p# _' q. Q9 \
  esac! @( H* ]$ T9 _3 s! C* R$ q# _1 Y
  shift
& H7 S# p/ f, m1 r# r& k  done% ?! U* o2 Q0 T$ F" z) `
$ Z7 }- b) Q5 d! K" w" X- o
  count=1. F4 N3 k- u5 e
  for param in "$@"
0 I; n. a9 w0 d3 j6 }" g: y3 C  do! Q% \& A4 g% t+ P+ ?. p: s
    echo "Parameter #$count: $param"" _# `) I3 h( u+ `& X* s
    count=$[$count+1]4 e, H/ M' j- V  ~- o/ m; R' x' L9 s
  done; W* A7 m0 u, H
发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:391 v: l# M: u; M1 A* f* R
请教一个问题
$ r5 w& f8 Y, ^$ g0 w# C有一句 :set -- `getopt -q ab:c "$@"`
* ~4 O- J% {& d: f. i请问 这个如何解呢??

% s8 V8 e( s# P4 {% Q) Z请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
7 K1 o0 p6 l4 R% G
 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
: `" d3 o- T& D# r+ h+ q请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
' O' h& D5 {  ^) Z. s7 G& J- i$ Y/ u
呵呵没关系,大家一起学习呗。' N0 |6 |. V3 W
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F
* K" s) x1 r, v4 {1 u6 C' b一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,0 O7 l+ _+ `0 n" @) e, J
所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。3 a  R$ N9 |; _3 L+ S" o3 g
如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--( K9 }& T# R" f2 U
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。1 [8 [/ m: M$ h' w7 t
补上昨天调试的代码
7 a$ m; @8 F( G7 S& G( _" ^
: g/ |; A4 s- p$ ^$ J0 m" ~#!/bin/bash
7 E* j: x/ C" D. ~4 Iset --  `getopt -q ab:c "$@"`; y; }' n7 R1 @  T) K6 W/ s
tt=`getopt -q ab:c "$@"`" T7 v7 f6 v& X9 z  ?  t
echo "\$tt:  $tt"
/ e! E- S6 d4 D1 U, |echo "\$0:   $0"
+ D8 f  @! }: _echo "\$1:   $1"
6 s, b1 N6 l! X5 L' G4 t7 Secho "\$2:   $2"
1 K5 X8 S5 a4 c& p7 U4 j. ^/ n' Techo "\$3:   $3"
: t. V$ Y+ K6 u9 t( y. _# decho "\$4:   $4". ^1 d" L# r3 _& [  W8 a
echo "\$5:   $5"
2 }2 g' b9 p" ~echo "\$6:   $6"0 a4 C; u4 F# x
echo "************"+ l$ U# y0 ?/ p& I3 X
* P5 [( {5 b0 n3 w) D& ^# z3 S

  ]% }6 d* R/ q+ u1 E' z% N8 u0 q  C
while [ -n "$1" ]+ o3 V8 P7 ^) [& j$ E
do
  `  X, E( k0 f* R  case "$1" in
) ?$ ]9 ^* H+ v  -a) echo "Fount the -a option";;
" }+ `7 C! v0 ?, l9 k
+ V9 ]$ j, P" o; L  -b) param="$2", R" T$ r5 {% ]: Z0 D
      echo "Found the -b option. with parameter value $param"
0 V& @  c: p- @. @0 h5 D      shift ;;. O) X) [& w+ o+ P; }( d! O

" M. O6 w; V! Y+ J, {  -c) echo "Found the -c option";;2 |" ^. K# f: R4 F$ ^7 o
; b. R1 ^8 C+ }) F
  --) shift
+ i; B3 _' k' o+ C! E" z      break;;+ p. m4 w! h) ~& i! q3 h
& p3 O2 V3 r0 f& M3 B
  *) echo "$1 is not an option";;
# [# ]) C+ k) y  esac9 e7 j9 J5 z. m; r! U" v
  shift; n+ Q3 N3 n# [
  done5 M1 y3 B4 Q+ e; G4 V  p) \6 S9 H

7 w2 a0 [5 F7 V: O  count=1$ g; j. V7 _; C. w, d  _) a
  for param in "$@"
+ q' x( i& I2 g5 |9 z; y8 W  do- _" L3 w* f5 s4 i' P' N1 e9 }' e! f
    echo "Parameter #$count: $param"% U$ Q% y8 q, r" a
    count=$[$count+1]
2 _% y/ t- X8 D5 H& z+ z  done$ i4 c1 A* T7 c% S- ?

2 a0 L$ `$ R7 D, R" t  s3 v: ]! O; Q9 ?# C
/ G# n. u  j1 [( ]& b9 T
 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test3 E7 A3 w' i0 Q, A4 j8 i+ i( c
$tt:   -a -c -b ''\''test'\''' --) n; m- G5 C4 B+ w; P% N+ P% M
$0:   ./getopt.sh
$ _' n7 N8 K( y6 Y. U$1:   -a
: V6 d( {; A0 q, H; a$2:   -c# ?+ X% i9 B/ o; P* c2 A
$3:   -b& n, {2 h+ l* ?' v! j- p3 Z8 W
$4:   'test'
) Q, D& h# @4 z1 t' j4 l$5:   --$ H1 Z, p1 W( J2 g
$6:   
  m% n5 E% @2 j, D' A************
- R' {2 B- W1 F" v1 fFount the -a option! R/ U7 N& \+ m: _" J6 n
Found the -c option8 R, u' l; o' \4 N
Found the -b option. with parameter value 'test'& N6 V! k6 Y- c
 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法) C9 W# c& h! S
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。9 h9 Q9 u. R* M7 n/ b
代码:; _% o* w9 h8 f. p
while getopts :ab:cd opt
. a9 U  z9 X9 l" ^5 vdo
! \; M2 C& K' Q   case "$opt" in
: u+ r' Q! L7 n( Z) g+ R9 b  a) echo "Found the -a option";;
- [: h4 M" B6 P  b) echo "Found the -b option. with value $OPTARG";;
9 v6 p1 d7 t. }2 w6 o  c) echo "Found the -c option.";;
/ D1 v! X" n- `3 [  d) echo "Found the -d option.";;6 I" y7 W( q2 X2 R# X
  *) echo "Unkown option: $opt";;& {2 X) |- q1 x: u& Z. [
  esac! @& x" y) b( c5 S7 N
done
3 }( J; D3 H( N  j7 X) gshift $[$OPTIND -1]4 V3 G. V0 f: y% m7 q$ t3 K$ x: F

$ x: k- s3 R4 N/ Jcount=1
+ |% d) ~) N, E5 k$ k" pfor param in "$@"0 j& K% K$ R) W, H* h8 R
do# f  y2 o. L& I* E
   echo "Parameter $count: $param"# ~! @' ]0 q, l% f
  count=$[$count+1]3 P) }' C& c6 B" X1 q; b6 b
done
 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。
/ n! f4 V3 q; l4 U其后就可以这样用
% g' U3 N5 I+ j6 |/ ^$ G5 [$ }- e./getopts.sh -a -b test1 -d test2 test3 test4' }/ ~4 e7 T5 x5 V" X7 a0 w
./getopts.sh -acd -b test
# D. ~! n( C6 \) d# ?4 l! C$ ?+ _8 l./getopts.sh -a -b test -c -d test1 test2 test3
+ a4 J' L9 k; k- p: m8 x/ M7 c  D等等
 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash! I5 f7 ^& i# O7 }! F
5 K! Y4 W5 f( O' @, L5 E% b

9 c* f' r) o4 D( }/ x' ~/ C6 j7 swhile getopts :ab:cd opt* {2 e- C# ~& G0 Q3 [9 V
do+ \) g- W  ?5 R6 S/ |2 ^$ s
  case "$opt" in
9 H4 _0 L% p4 h: t  a)echo "Found the -a option";;6 G" A: }( ?- B2 ?
  b)echo "Found the -b option. with value $OPTARG";;; U& G7 W! S5 }# @* q
  c)echo "Found the -c option";;
/ G& ]& ~+ A% L( L4 j4 D  d)echo "Found the -d option";;9 V0 x6 t" z% F+ K6 Z
  *)echo "Unkow option: $opt";;/ v( J# _' A1 n; `. L
  esac' {) W& y( k/ T
done5 ?' a# x* ^: M: W9 `
$ A  t9 p4 y9 Q3 |1 |
echo "**************"# n" y' }" B% S
echo "OPTIND: $OPTIND"
' w5 w: P( [4 C/ K echo "\$@ $@"
* K; b/ C  `2 @5 J shift $[$OPTIND - 1]
5 b- b  p9 h3 s" @! l0 B echo \$@: $@
$ P0 J5 c# ~0 Y% v; M5 a% v. ]: G& N echo "**************"
2 ^9 S1 X1 ], a; ?( q+ [; ^9 v5 F+ {0 p# O" x/ h+ ~
count=1
  v. q  m$ U3 u( `% ?0 \for param  in "$@"  Q, R$ g7 n( [* p( ~# B* T
do. l8 h" P7 f0 m  S
  echo "Parameter $count: $param"+ R- G8 q( E2 V1 B
  count=$[$count+1]
3 `# a3 r# z& a* X4 _0 wdone & T/ l; K) M/ z/ m3 k4 c/ w: ^

0 l+ j( O: M7 @; r* @' s6 q
( y# l, t# l4 X, h3 p6 Y- F9 \! l5 ~# v+ L* m& e* l- ^( T4 ]9 O, E
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过% P! M+ @& M  v2 {, J' P

( V' z# k: o, C

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-18 16:57 , Processed in 0.054772 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表