一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

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

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

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

5 J! Q9 R9 l: f+ dgetopt/getopts:Bash中命令行选项/参数处理: X0 I3 }$ D1 L0 N/ F7 V) X
% Z8 P2 N, _! r
0.引言
8 D$ g1 I! T* M: A" H& {
' N% [0 G. Z: }( f: K( d& E写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
" c7 Z% [  y! m) `) F! R/ v/ Y$ [7 z0 ^0 r
选项与参数:! a: ^' [: q2 U: h3 v

* u$ h: ]5 [$ K& [7 t如下一个命令行:' p, P. \3 |8 Z2 o: E7 O

0 n* M+ e3 _% _6 H* P9 [# Y[vb]
* g8 v6 G7 y, m7 u./test.sh -f config.conf -v --prefix=/home* o' ]7 X, C0 [0 b& E: E2 B9 b

" F5 J3 {6 x/ }! b7 |我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。7 A9 G3 h3 ?; k- t, t
$ v. Q& a, K9 P( j7 ^; }
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。4 o" W$ y# C  z: D. B" L9 x

4 {% ~# W+ y) j- Z; P# V在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
4 R! c  ]1 u% a
1 p+ }0 m  |, f3 S3 o! _) L4 Q9 I6 Y手工处理方式+ `8 U/ ?  _6 F. e. L2 n8 t
! Y4 J4 J1 Q2 c3 ^' r
getopts
9 w" d0 ^/ Y' u! o: b
) R5 M$ Y" v2 X) pgetopt
" M8 |$ o7 r8 z
8 i( d4 x" R! e; K0 Y3 o下面我们依次讨论这三种处理方式。
8 y% v- M) W2 s; @: ?% k) G. q7 d$ I! ^4 ~1 N" @3 `
1. 手工处理方式- n3 g/ d% f8 C: a$ u2 F
1 d) M# {( H  c! W* F/ X: P
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:- A& A, t$ d* n0 E3 z' p
1 r* b& ~4 p( p
$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]4 Q9 s' ?: K( a
$1 : -f,第一个参数.
. I: Q+ c! z. S7 S% z4 R
3 S# p: q. C* O. }! q$2 : config.conf+ x( c! t6 W( S0 |6 R" V/ s
, V0 y' r( c( u$ ~' Q: A  T
$3, $4 ... :类推。" E( L2 H# n, P1 ^% K

* y$ J6 S* a! ]6 ~5 r$# 参数的个数,不包括命令本身,上例中$#为4./ n. ~, o7 r0 b

2 O* V  Z' S1 z5 D% p$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
0 ~. }# `4 N7 T! D/ {9 k  n& U' O7 z# D' I8 r: v: e
$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:
  S; H* v0 K4 f2 Z' h
1 [( B' }1 i5 y" e) l[vb]
0 c# e$ N. F0 h' C6 }+ m# ^#!/bin/bash
" l6 {% y# P, Z4 t0 T* M$ q* q0 J' L& s0 \) B
for arg in "$*"
. Q4 o2 F" R2 ^3 K& V8 X' x' H  |3 o1 Q+ A6 h* h0 T
do
6 `1 r5 U  i9 ?+ b: r) U/ S
7 }) G& h, `5 a- ]: F8 g" Cecho $arg
0 P' G3 W: a. w* o5 `0 _' p
& x  W' b  P; N9 V1 J5 i( mdone. R1 f8 Q( ?8 f' @' f) _: x
. ]1 i+ _* O: b% X( J) C5 w6 Y
for arg in "$@"
' x+ p- B, e3 ^: ~3 P% \* z, p8 O' ]( U
do
# ?4 v0 K: M# ?7 G& g& |( I9 K9 d# h) ~% d* I* p
echo $arg- k2 w- r% E  N* Q
, U, S8 Y1 {6 X) t
done
7 l- z6 I  G! A6 R4 X7 A$ t
# w( s: T4 c1 ^2 ?  r执行./test.sh -f config.conf -n 10 会打印:
2 a, L% K7 x; i. [$ ]  ?2 N8 w$ X4 A& ], t4 v0 v3 R
-f config.conf -n 10 #这是"$*"的输出
4 A) _# n5 F' V# _  X& V$ H
* ?* T0 L* k- V0 i' E' y6 j& \#以下为$@的输出& k) ^1 w# q! |: ?2 o6 R8 A

( j3 y9 O+ m8 G( \-f
3 s; k( [6 L. p. }7 H  y' R9 T! p3 A) @2 q0 A$ P5 ~
config.conf
" r+ V$ d  {! S, f7 _$ E$ G2 N; ^" r4 Z7 Q- U) `' ~" q/ Z1 b
-n! `- n# P  ]6 |( m' ]4 X& J

: m" |2 b  J3 i* ?4 \' C! ?' S10
, _# x& ?: X- L( }7 E
9 |& P; h' P! b6 i, |0 W$ p* J所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
$ P: g1 O9 w& I/ j
) X9 X, z0 l0 [( c; ?+ g  b) H“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
( y2 F7 Q& G- J/ @- l& o$ y/ V$ I: l- ~+ q
[vb]5 s0 B; t6 n+ V! A* \8 ^# M& v
#!/bin/bash" ]  F+ u2 s" R  i
# @- i  p. x2 C# p. m! B
#if [ -n "$1" ],参数不为空
, k3 W9 Q+ t2 Z- ~if [ "$1" != "" ]
5 y* i7 d& w' U1 L! pthen
0 n8 K9 [! Q1 U4 h7 p0 T$ t2 Q# C2 i2 ?  C% m
#...有参数, K) w* H! a. U0 C2 L

. t) S! h; p% P8 R, Qelse
. m8 _& f9 L" o, c
6 f' o& V7 ~, V  ^$ D4 qthen% ~0 u$ m( {  x- o# @' [
' T* o* v! o: y! p" Q2 q, Y3 R& I! j
#...没有参数% D  c" w' p2 I- ]" ^6 L$ U: T
; B5 _- _& f) U; n% |" s% U
fi2 e8 E- A( [( i. e

% D& A0 r& I) i7 x手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
8 [' H( _7 q5 u( t% K- K" B% S; y$ X: E6 c5 U7 y3 w
2. getopts/getopt
. v6 ]) r7 o, Z) k2 @2 T1 F' z
8 @0 S- j0 h, C; E处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:) Z: \- J7 E2 B" F- C, ?3 W0 ?6 q

* E2 F$ R3 s  ~4 P) N./test.sh -a -b -c : 短选项,各选项不需参数) c4 F6 I, f. x8 K' e

& @* m/ `0 o: ~./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
# j4 s/ k$ k5 s8 ~4 W, U% i
' R' X/ w' W+ G6 N./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
+ w2 [: g2 c  F  N! j( w: [- ^; G  u1 \9 z% V6 f4 G) R5 h
./test.sh --a-long=args --b-long :长选项7 e# H. f. i  ^6 e/ h

7 C) t& T" _: Q我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh/ g( _/ u, w- }* a. ?
2 Z9 ?; Q& x$ W2 d* v* A
[vb]
$ b6 m% Q/ @0 L3 N, R#!/bin/bash# \% O* |# f2 M1 W
( M8 v3 h* t% r+ ~  A
#选项后面的冒号表示该选项需要参数8 F( w( B/ V9 g

% G. U) V% ?; v) l7 Z" ?6 B6 `while getopts "a:bc" arg
# o; P/ O9 A1 c& s/ c8 {, G5 k! s, X+ b
do
* \/ h- e* C: v9 C
1 m! n% K7 k3 zcase $arg in: C; j3 x, C' g! H7 F

6 X) n: S  n; Ta)8 `/ ~* B8 I; T' {( l7 Q
- \. C+ V" m7 ~9 h6 {7 y
#参数存在$OPTARG中
/ W/ D: n6 v4 s; [
3 x. R* u! D$ w) y0 Z3 |echo "a's arg:$OPTARG" ;;3 n1 b. C# e( b+ \! p
& H% ], m; c* P. }5 ]9 ~
b)
! w1 K. f; N4 {6 p# Z" U0 P% B) Y2 E8 a
echo "b" ;;1 v' v8 L7 ]* S' _7 E6 d
! M0 {  k; K$ w; b1 E' ~
c)
7 U, Q) \# h, G) A1 I2 L
- _  @" A# z0 G1 [7 z) Decho "c" ;;0 }# Y" `4 Y/ Z" Y9 D1 `- g" F8 B

$ s9 L3 \  q& a! w; v?)
+ C9 W. X* F  g# a3 _9 z  M5 c1 E. ]( u, x0 U4 J. e6 E; Y/ r
#当有不认识的选项的时候arg为?* L% b! O) A1 E

$ p7 w% }' C5 k0 P& y% techo "unkonw argument" exit 1 ;;
$ d: w. t3 J& a" b5 r- j
. X& G1 i4 {, J7 Uesac  j7 ?/ W4 _/ _

0 x( h4 r5 N/ n& Q7 n& bdone
% Q; g- _0 T) ]1 r. D9 V
: u( L# U. l4 L现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
* b1 A* d& u8 B
7 e# Q3 M7 I" f0 D2 y来加载了。: }7 ~- u* [/ L4 N( t# u" H
/ X6 y& F. T! w- K" e
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
5 [. u# n" c0 k- l  E; Q) U9 U* p, u
[vb]3 M* D/ ~2 P% h- Q5 W8 P
#!/bin/bash& z; Z% `5 O9 D% r- b
  N& R. m* l; [8 S* Y4 E$ y
# A small example program for using the new getopt(1) program.
: \* i6 I5 \8 S. w
: C: q2 {/ y+ S/ p3 N+ @) ?' z# This program will only work with bash(1)
) e( G/ J: A& {- A( D- D0 a8 [& M: x# ^: U9 ^: L
# An similar program using the tcsh(1) script language can be found6 @$ _: k0 w8 t; \* w
' M( }2 B" n; X) Y" u
# as parse.tcsh
+ h9 ]5 j' N- \; O$ Q( i: ^6 X9 ~* v; R  D9 I, y$ q  L
# Example input and output (from the bash prompt):3 W1 f6 a! a1 Y5 ~2 B

5 _5 }+ ~  k8 u+ X6 y& W# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
) x! L& J' `# L2 ^3 K
) y! A; u! \- `4 m7 A1 g) m, {; X# Option a- [  i' f+ K$ b% ^# M) ^
! O& }2 p5 H3 f
# Option c, no argument" T' ?- U" M2 n# E: F: T! u7 N7 g

3 @: F& o9 r- K! `# Option c, argument `more'
# n. ~& a) V, @% R! y4 `' Q/ Z. I6 G, j" Y
# Option b, argument ` very long '
- R# \+ B) o& b
1 c% Y/ x% i1 q9 |6 O3 Q0 r# Remaining arguments:
  T; }8 _& Z- t3 h' s+ M& Y3 Q
" V. z: |7 Z  m# --> `par1'9 p% O/ t% J9 l
  u7 x9 S5 T: `
# --> `another arg'
) D+ H' r( X- V- A9 k' e# q/ H9 F: q; J1 k
# --> `wow!*\?'
5 N5 l" `$ Y' T  s  ~4 ^8 K/ `& `0 E: w
# Note that we use `"$@"' to let each command-line parameter expand to a5 ]1 T) m! G& I1 q$ S

6 l0 e9 h# g- q. k+ B8 Z3 K3 }; e# separate word. The quotes around `$@' are essential!& I) l6 C+ T0 u$ E) N- K

, F( k7 R3 ]7 |1 `1 q0 u, G# We need TEMP as the `eval set --' would nuke the return value of getopt." \4 y: X: _5 D  u9 D7 }& N  g) T$ U

- M* Z9 J; d0 Q3 W! S#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项  x* f  U9 w9 _* ]0 p
8 \2 B- \" r/ |$ ^+ V' U, l9 o
#如-carg 而不能是-c arg! Q* y3 W7 N1 f4 C' }: X9 [
$ {/ L4 A8 W; ]1 a) B
#--long表示长选项
. ^  }1 m' D% y' r8 W
$ {% a- p7 N9 c/ m0 o#"$@"在上面解释过3 Z) p: _4 j* Y" U9 {
- U; `- g% D5 q4 Y& H. I/ g4 P
# -n:出错时的信息
/ n% O# R1 o- v* U9 E. b8 b% }7 I. u4 M2 D1 f' Z3 J. Q
# -- :举一个例子比较好理解:
7 f2 S" ~( W3 S7 d( ~0 {! n2 H* {2 X' s* {6 [
#我们要创建一个名字为 "-f"的目录你会怎么办?; ]1 V% m: _! v8 W/ I
" i: M4 W; I- ^
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用* A; `( A- `1 f+ h

$ U& x' a- |6 E7 q/ L, |* [# mkdir -- -f 这样-f就不会被作为选项。% n" N/ E: M6 T# R! R! G

, v9 E3 ^# ]2 l4 s/ BTEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \/ a4 F- g/ J% F8 h" w% M- b

. M. H$ i( O6 G: z9 h9 i/ ]6 _-n 'example.bash' -- "$@"`* h0 \5 s  O! j. Y

1 Y: k: ~& I. e$ b4 c- v# qif [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi , G$ n" }4 L9 Y- z
# Note the quotes around `$TEMP': they are essential!3 ?" q* Q/ p3 Q) D5 v9 c3 m' ^
4 ?! w0 X2 u2 a# A' p& s% n* R
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了8 x# a& O+ w# `) e
: Y9 J) k6 \  _
eval set -- "$TEMP"
8 p  F1 s% w) x8 [* W7 ^1 x$ |0 Q, a: @
#经过getopt的处理,下面处理具体选项。
3 @( c+ E$ u4 z1 q7 Q- s' X  ^5 }( ]* G0 `7 e" m0 P
while true ; do5 P  W* |  o+ E! }2 J: L5 X2 }
1 q! A& L, [7 W4 F+ d) X0 i8 D: H8 E
case "$1" in$ S4 j/ H0 G( b4 @' [1 L4 Y

8 w5 a1 |# K8 ^) \" T4 X& r-a|--a-long) echo "Option a" ; shift ;;6 s, c' j1 h; m
/ c6 `: g5 g2 {, w+ v1 d! {
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;9 {* m5 v' z. |% A3 C2 [

1 x3 h  h/ ]0 h" Y( l% P9 B-c|--c-long)
' G$ u7 {! ~# t+ ^) V7 j! d; n8 o4 C. Y1 ?: i$ R5 I+ Y. r( @% s
# c has an optional argument. As we are in quoted mode,
* N4 ?. S" \% e& z) Z! }
  a4 a6 }! R# K% g  J! d# an empty parameter will be generated if its optional8 m# v) J" a/ i
) {& _+ H( k0 Y5 o5 o. `7 j. A" \/ ]/ i
# argument is not found., p. K8 g  U' |4 B: J1 `- w
# W# M" a  i/ k! R/ K4 x
case "$2" in; w1 }3 B% r4 _! N- J7 F
8 u" F& j, F; z: `5 Y
"") echo "Option c, no argument"; shift 2 ;;
  F1 {, U9 R: M: v1 v( Z6 x) x- S0 v  [# d9 Y2 _) l
*) echo "Option c, argument \`$2'" ; shift 2 ;;9 A" E5 Y$ `( W% |& P

2 T$ K% F9 g% S( o2 W; S9 x$ Yesac ;;0 Q+ m2 N& t* i' ]/ g0 R
' @$ t- S1 t6 |7 t- F& k6 l
--) shift ; break ;;- `; Q, z; k" c- V, X/ N

5 U! w% ^- `  {/ i' c*) echo "Internal error!" ; exit 1 ;;1 v. r; f/ u, a( e6 h, L4 f
' X: n* l9 k. f  }9 o4 s' y
esac& v+ g/ {! {& A. N1 T' {) ^

- Z& ^% }& |; Y# Zdone1 r$ z9 i  K5 \- i) Y' P% c1 X1 B
5 C1 D* u7 v5 F2 L5 O# V: V
echo "Remaining arguments:"& t/ v4 x  L3 b! H# a( a- @3 P
' ^; Y0 |2 V8 N* T
for arg do
7 p6 g- e9 y# Y7 i; B: y# k9 j! E/ g( U) f
3 ?* j, O4 `; t0 t! V* Z* f* `echo '--> '"\`$arg'" ;/ L, b6 O7 A! |: S! n8 k- h8 G
5 J' B1 J) q$ l
done
, q1 O& U2 U8 S; T; a* i+ \
0 S: I7 ?; C; y0 e4 f, O& T- z  ^" c4 q
比如我们使用* @$ Q0 A. u0 @: o
' b0 o( ~; H- G) M; C7 H
./test -a -b arg arg1 -c, P0 g! Y8 `- _5 I- y

0 B. M4 N4 [) P# |5 m1 J你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
  z' Z" Y2 q+ t: v+ W  ^4 Q- A5 U: m. m+ O+ e" N! E& w
-a -b arg -c -- arg1
' ^& y; G" e- W, L6 b- J; i. Z4 \: `5 h$ V7 [
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
) L" |3 m, S; M, X  Z" g8 N7 E  O8 p) t0 n0 g
3. 总结
6 J7 Y! r( @7 D8 ^! k
& A. p5 x8 d3 R' R2 e& L4 P/ I2 ]" d豹尾。; W/ {. E$ l% y+ s+ J9 E
' j* F$ \4 w5 ^' K+ ^2 |2 `( C0 P
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统! P/ S( p" N% \3 G! {
* X1 C! L7 J9 L- v
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
$ X& |# f; ^" J, H& _! N# g- K记得getopt常与shift结合使用,while循环一下就好了。

. Q# O; G7 Y/ G" `6 k+ J# {请教一个问题; t2 A: G6 t; P& f( B4 ]
有一句 :set -- `getopt -q ab:c "$@"`
/ ^+ G- e, {6 V; x& d请问 这个如何解呢??
% O* T( Z& z$ D1 L
 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句
* x+ A) G+ w2 i$ {set -- `getopt -q ab:c "$@"`# w. M( T  a3 I! P
while [ -n "$1" ]
2 q" E/ F* v. O6 F1 _8 R* J* \do
( J* [. _+ @% q* Z: f* }. }; {& u  case "$1" in  s2 Y) q' P& P2 @
  -a) echo "Fount the -a option";;6 y/ b- ^/ C. j" k; T+ ~; i* K9 A
2 c# z+ S4 [4 z3 w! c1 {
  -b) param="$2". r  }# N5 Z. x2 `
      echo "Found the -b option. with parameter value $param"3 C! X5 b4 L) M
      shift ;;
9 G: E* p6 R% H3 E4 c- W' h: r# ~( m+ `
  -c) echo "Found the -c option";;) ]7 Z+ b" g5 b

2 T0 b8 I2 O2 a  G4 X2 Z  --) shift* }3 X- Q( N4 T6 Q8 r, Z; Z
      break;;' L; Y4 h. p- A9 C. Z) h
$ `! v- F+ G' ]5 Z+ c9 x1 G
  *) echo "$1 is not an option";;
9 @. b% O1 N. @  esac
$ u5 l# S( S  X# [$ T- o9 ?  shift$ ?, |3 k& I* G& J
  done
/ G4 v" ]' f7 q6 t+ e % H; G& Z( k: r0 E* v6 t* U
  count=1
. @) J- }- X% d! C- M  for param in "$@"! g# O" ?' M" e# _! L
  do
. n6 G  b: i* r    echo "Parameter #$count: $param"% Q6 V6 F* N$ N: f4 }
    count=$[$count+1]
; g$ Q8 C" w- z% f  {, ^: ^7 x! P  done. y& o  P! p5 {4 D# t
发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39
7 {, |' ?. ]" T* E$ g8 |" T请教一个问题6 ?$ e" v  B! f- @
有一句 :set -- `getopt -q ab:c "$@"`6 a0 O4 g; D7 ~: w) G4 r
请问 这个如何解呢??
& {' b4 d% J( T
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
$ h5 [5 r- E2 _$ ]( O, u- _% p
 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12" s8 x3 }; E8 C0 A# e0 \5 A+ [
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
* [, k0 O0 M4 `, U& Q- L6 L
呵呵没关系,大家一起学习呗。8 r4 D) R- J* |9 x6 Q# }- e
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F, ~0 L  v! p6 [% \
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,7 \! j& Q; k4 G) R. Y0 n* M8 X
所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
9 S1 Q  |9 a, f9 ]& M如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--% g7 J" j# Y3 ^) B6 e  Q4 m
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。  \% V0 x! q  ^& u
补上昨天调试的代码
+ v& E( E  L/ ^; n; i  r  p9 P+ Q: o$ t
' g2 h9 R5 }- y8 Y% ^#!/bin/bash
9 I; A% W7 O' `( X' T5 C) {/ ~; ]* jset --  `getopt -q ab:c "$@"`
& O5 P- ?( k4 X/ stt=`getopt -q ab:c "$@"`6 N* a* ?3 E3 G* e
echo "\$tt:  $tt"
$ O  a$ I. k( F% W8 N9 |/ q/ vecho "\$0:   $0"
% x8 S( j( N4 V* Jecho "\$1:   $1"
; r  G% c! g. @; ~echo "\$2:   $2"
+ h! w. {2 L5 `* ?' decho "\$3:   $3") n/ C. k" B. F
echo "\$4:   $4"
0 F5 T8 ]" M8 z  X& t% uecho "\$5:   $5"( X/ X0 S7 t9 Z& M, D7 [
echo "\$6:   $6"1 ~# {9 }( E8 R  B# A2 ~
echo "************"
" x$ i! N7 s' t4 y
5 p( Q& u: R$ @4 _  q8 E+ x
2 q0 q9 ?& b2 H4 u
" o3 r: @1 S. t2 }& ?while [ -n "$1" ]5 o, C9 ^8 H; U6 o+ k
do, d/ e  P- {( D+ ?
  case "$1" in! h1 z+ n1 e3 C4 h
  -a) echo "Fount the -a option";;
+ D6 b" T) d% b, v2 I
/ P2 C$ B  r1 L% n/ ?  -b) param="$2"
. V* g! |3 H* n) R      echo "Found the -b option. with parameter value $param"
6 x: }3 m) G; F6 T      shift ;;
2 c. t5 L: Y! v8 O9 G2 \
9 U% B/ P# L( d7 O0 p8 e  -c) echo "Found the -c option";;/ h" s# x! }$ v) G
: |, d0 W5 E) g# q. C2 e0 y
  --) shift1 `; c$ n; s4 x$ V, H/ t" d
      break;;
0 Y. ]0 l+ ~- q/ R* t4 _5 d5 r! u4 z. V
) w; v% B( U# i: r  *) echo "$1 is not an option";;( ]+ a$ U1 y/ d3 r8 `: w$ p: L& T
  esac
: c  Y: R% d6 _  shift
- i; u) x5 I9 |# |, Y; L/ F  done
% F6 S3 ^0 c# U' U
; Z" e3 A% Q+ f4 S' G+ @  count=15 c6 M9 ^' u+ w3 ?9 s
  for param in "$@": B$ D5 D) Z$ L, M  V$ k
  do
+ E6 ~7 D/ z7 f- e, h/ c    echo "Parameter #$count: $param"- ~" T3 W9 M6 [  Y! ^0 ?9 T# H: l* o
    count=$[$count+1]+ A6 ~: L9 R' L: m* G
  done0 m! v: A: x  D/ Y" r

: [! i$ {5 u; ^9 k! E0 {
. A+ V1 l1 n8 N4 |8 H4 O
" k- F- r" z! O: ]( L9 _
 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test8 C* ~% k% [! r5 U% }; F
$tt:   -a -c -b ''\''test'\''' --
' @' ?* y* V  a5 @/ a- u$0:   ./getopt.sh7 X( a$ M  n- ?# {
$1:   -a
& @. v! w7 i( N" K- {0 M7 C& Y$2:   -c8 L3 T7 r1 t' p; P9 i( L/ x2 z
$3:   -b7 @8 v$ X) z! h# c# f' a
$4:   'test'! A7 J+ q0 Q8 P" T% X
$5:   --
1 b3 r" N8 l" P$6:   ' n$ V4 h+ ~! ^( h5 n( F
************# o3 A7 ?; J( d# E! B2 Q
Fount the -a option5 t& s2 a" C4 g! S( t
Found the -c option8 M0 R6 M8 ?* @" Z
Found the -b option. with parameter value 'test'
8 b' ]- a( a7 i, s& a" G9 E0 R
 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法2 ?+ Q# @/ l3 S& y2 z
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
! q& F' W. d( q5 u8 d代码:
) e" |; J& O, J8 T/ n( ^/ Gwhile getopts :ab:cd opt7 x. C: F0 @  J/ V# p5 n
do
  `0 F0 ?+ L! w4 D   case "$opt" in5 `# F7 a: E8 O4 D$ P* T; X
  a) echo "Found the -a option";;
3 I* |0 {: h5 j' Z# ]  b) echo "Found the -b option. with value $OPTARG";;
0 L( F3 D9 z" G8 E4 @/ G& G  c) echo "Found the -c option.";;% m9 X# M' x9 s! Z6 c9 ]8 Z% ~; S- K
  d) echo "Found the -d option.";;
- D$ U1 p4 R7 W, e7 n* K% n* }; L  *) echo "Unkown option: $opt";;* [0 s0 q8 o0 C# w: H0 s1 Y$ B1 c8 H
  esac9 {2 f% G8 W) U8 J
done! a9 P) r3 y. \- ~
shift $[$OPTIND -1], v+ p- q  K  F! ?3 r" X1 n0 R  S
9 T0 b$ ~5 N9 A
count=1% f2 E- a2 g6 X" t. f, K
for param in "$@"" c1 ~$ y. f$ y! h1 t4 W
do
  i' Q: G3 k( Y$ ]. C   echo "Parameter $count: $param"( h) C7 t/ N) `$ B9 o5 G9 }5 S
  count=$[$count+1]
, }" d6 z4 d: T; Kdone
 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。
: U# p* [6 M( N9 D5 U其后就可以这样用
. }+ M, R2 S( o( Z0 K1 ]: M9 M; T./getopts.sh -a -b test1 -d test2 test3 test4& L4 R3 _6 n. L& S, ?
./getopts.sh -acd -b test1 l# f5 ^/ c5 J$ E6 m, z; P# D" H
./getopts.sh -a -b test -c -d test1 test2 test3 $ U: E, |2 `4 [$ K/ B
等等
 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash8 o7 A$ ]$ s* o3 ~
# `! }' W, n+ V
  w, }: ~4 }1 `- d# s7 C" @* q9 A( n
while getopts :ab:cd opt8 ~3 V0 A2 v) @! a& k- Z: g" E
do
6 {  l% k3 r* L5 G  case "$opt" in
* V9 l* \' |/ G$ G: ^  a)echo "Found the -a option";;& L+ @9 D" i  d8 V3 S
  b)echo "Found the -b option. with value $OPTARG";;
: \9 x  c- J# Y: q8 m8 ~9 l  c)echo "Found the -c option";;) |" K0 Q/ Y% J" r
  d)echo "Found the -d option";;- s6 N! X# }" t; q* q2 S! X9 R7 b
  *)echo "Unkow option: $opt";;
* n1 Q8 O/ u% O. P0 v7 H, {  esac0 n8 e% H+ q+ r. S4 K! d
done0 k0 L# ~/ W: w: {$ e. b
6 e: u. M. m! R0 L# n' h- ~: N
echo "**************"
) Y. J9 |, o. d/ G echo "OPTIND: $OPTIND"3 x" S' u9 O0 X1 i. J
echo "\$@ $@"
5 Y- J/ F  j9 f/ h4 q! A1 k shift $[$OPTIND - 1]0 B& }9 K6 L: ]7 P! E: }/ G
echo \$@: $@
" l& K- A( u, F. I echo "**************"
) U) E# q0 g6 n$ g0 {5 t# f
' Y8 B( t0 k) @: V% l* B" a" i2 Ncount=1
; x! ?% }3 a& Y- A# Lfor param  in "$@"
& A2 f3 `* H$ D) O" Cdo
+ Z( W$ w- H1 s8 _3 k0 x& E  echo "Parameter $count: $param"- |4 ]6 ^  ]0 U9 s
  count=$[$count+1]' t0 K  Z9 V7 e1 w* `
done
  Q& T3 q- Z6 O' ?8 X
  I+ ~) n# W- C
# `3 x/ h$ t2 Q& t3 B
7 q/ O; h0 I3 ]; Z; b其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
& s) g2 E5 P  j# [8 F) `; X0 `3 y+ n8 S6 N7 p

本版积分规则

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

GMT+8, 2024-5-5 01:34 , Processed in 0.065472 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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