一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4776|回复: 9

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

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

: N# N& l. O' ]5 |7 ^0 Hgetopt/getopts:Bash中命令行选项/参数处理( l( Q) p3 s% m9 p
( T+ y- T0 P# O: s
0.引言$ z) u/ M) w& P" l, V4 i

6 Z; e  R6 ^# \! g; F3 a! R+ l写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
; }8 g4 s" B- b+ X6 P3 _1 X) A& p
. u% k9 a/ C6 H' ~. _- z! \选项与参数:
* u4 T! k% U9 g6 |( L/ n1 I! |! H2 K9 F2 B) N+ ^- g
如下一个命令行:
% X9 t$ e( {% S+ K3 o
1 Z& J1 t: x( `& Q( S+ y1 o[vb]" G+ M+ X2 i; s6 t
./test.sh -f config.conf -v --prefix=/home' u2 e5 U: u! T
# i5 m0 ^9 C' s  q7 _
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
6 K- L' K7 `/ b0 @* i4 g& o" k  z0 M2 u& H5 F: P9 r' `
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
* a2 F2 p& W; h+ n9 I7 ~
% T5 U- j1 `* y/ a3 K) k" l在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。( v4 P+ }; m4 t" |3 b3 H
; x6 k: H: H! m: M
手工处理方式
& ^8 w2 G5 t8 a3 g2 A* A& C# I8 h$ K5 w
getopts
+ ~4 q9 F& R% N/ h6 ?
' V# n, Q( I" u- z; Rgetopt
7 d" Y3 `! |1 f9 _0 n( ^4 M5 A% O( n) y! ~" G: g9 h
下面我们依次讨论这三种处理方式。
+ S+ @0 O5 T/ C6 K6 |& A9 ^( ^! g4 u% x
1. 手工处理方式3 w( |" k& D% k

% v9 q% k9 p+ h2 Z8 G, L  a. c在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:5 X! C% [# G, E( |- r: E$ g

& ~# B$ ?4 f) s% f- M: d7 a9 c$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
/ u8 V- o4 k+ B2 q$1 : -f,第一个参数.
, R( h) i6 v1 D' Q  D2 G* @: u/ T1 \$ l2 ?- g# L+ [
$2 : config.conf3 e6 P" b6 @& d6 @$ z, c+ ~3 V
; d" _$ l7 E; e. k
$3, $4 ... :类推。
' Z8 s7 K  X, M0 u) O& r
0 x9 B* R! E; Y7 I9 u) I9 O# t$# 参数的个数,不包括命令本身,上例中$#为4.$ `8 I6 O8 M# D6 C) W

5 G- h3 v7 j  }$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home- ?9 J+ i; p5 s. u( ~

9 [7 r( ~, H6 W- s+ b( u6 g$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:5 `# C0 F/ k$ q* G# B/ b

4 i1 \+ d' a8 `. w- R$ b8 r[vb]5 C1 i0 }) b# E+ Z: q
#!/bin/bash
+ N- N: J, O8 {# f% f* J  D3 I; \$ ^
for arg in "$*") C6 J% ?. u8 y' N0 O% T
, z, D/ m$ k& [9 s
do
! I, d: f  q' @  }4 \6 A" p& w/ |' O: i2 o. _, I2 G7 P
echo $arg
" M* K5 l. x8 g' k* ?" D% T& F7 l: o0 l1 O8 x! t9 t. ~
done
# C6 o& b4 {4 {' q! O% v' i7 ^& e, r' D- D) i5 R& W$ O: j# |" }) r9 P+ i0 p& e
for arg in "$@"
# f4 L& V% I4 ~) c( f. a9 P
4 v8 R# R6 @4 M, t0 f3 B" R" vdo
  w* t2 R! I5 C) H# ~) U. \
3 J' v8 O6 z- V0 u) X1 F+ l" }& hecho $arg
, J0 X6 y! V0 J4 I* U4 Z5 f# u# _- t5 O  @1 o
done
* s% A" k/ n  e. W
) ~2 V1 K4 I$ Q执行./test.sh -f config.conf -n 10 会打印:2 |4 _  `/ T* d3 `- s: r

: `$ C1 {) |5 G-f config.conf -n 10 #这是"$*"的输出
% A9 u# y! E" X
, ?0 f* b1 l* }6 L3 G- \#以下为$@的输出, W& F1 P; l2 f+ a% b! o2 Z

  Z% U% w& L* T. f-f% V8 S0 m+ \+ V9 p

4 K) j8 p. ?( F. g1 R# Lconfig.conf* H' \! d6 y6 d3 f

# f4 C! m9 ?0 |. O-n
, A, d- q) y/ g/ s6 u# i  Y( p  K+ Z: T8 p4 @% V  _, d
10
  F2 w1 s7 R8 C7 t
- i. e! M+ R4 N4 Y7 }2 ~; K所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
0 Z/ _! t5 V' S+ C2 ]0 ]- e2 E) M% I, t! @$ E
“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
1 Y# ^) I  ?" u* F# y$ S
+ M( I* Z8 e. O+ G; v+ m* V0 x[vb]. i1 e% D4 K6 n3 H" A
#!/bin/bash* }' E( {% H, m0 e5 [  B+ ]
$ |1 Q1 ~. `) r5 T' J) o
#if [ -n "$1" ],参数不为空
0 V9 g& O, b* ^& A2 Z( G% r6 xif [ "$1" != "" ]
$ M9 J+ u4 s; I$ c7 Cthen
$ I" Q6 y9 `7 ]
! t$ h+ j" j& `#...有参数: j& q/ T! [9 G7 _- o/ K

  o) u3 \- a5 T0 f& X6 z" S" T9 ^else
& m5 ]& `% K% u! f. m" F& Q6 A
( g/ e$ b7 \/ u) Ethen2 u+ V  ^6 x3 |6 K

2 I& Z3 g- c+ I8 K, F8 e4 c+ X* x#...没有参数% g7 D1 e  c; i
* f( q. O/ M7 J# i
fi
' G$ A8 P7 Z, U$ O
5 {6 p2 ~2 `6 d9 }, ^2 ^; q8 Z6 S: b手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
* t' L% v& x8 p6 |1 c8 D: F$ L: v9 D: q8 H6 R4 Z6 ?
2. getopts/getopt
2 r$ _% a  @9 L6 D9 x7 C" @, c( E' H4 \: q
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:
! N! @& ^0 m9 J+ N! P9 R
. g( e+ W1 O9 d  k./test.sh -a -b -c : 短选项,各选项不需参数1 T9 d, r2 Y+ x; V) `$ V
0 j, {' ^# _! h8 U& }1 h( @  I+ D
./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。/ w8 @9 r8 `( o

4 f7 c  D1 d9 N( x./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。) q8 h& R. G5 ]6 V

# j9 W- h5 j* S$ I" x./test.sh --a-long=args --b-long :长选项6 l3 D% u6 O% T1 `

1 P5 b  v' V* C我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
1 I1 l- h8 V' c1 V  E8 D
5 q4 _. v8 g) v8 Q3 A# r( Y[vb]# r. H7 ^  m! [2 V& d  L
#!/bin/bash
& R9 `' C1 k. z, I& r2 s4 M" N& s1 W; y$ _
#选项后面的冒号表示该选项需要参数# `  g3 x2 w7 v% P5 ?! G) x
3 e8 k) b( ~. v3 s2 n0 D7 ?+ h
while getopts "a:bc" arg
9 F: Q" J! j2 Z0 \/ t
; c% y: q7 M) U: Fdo
1 [4 Z- F2 W+ r' S
2 `- ]  v: z& M1 Gcase $arg in$ X4 J( W4 N$ f
. [6 a- P; U' v% G6 C/ _0 F
a)
0 e9 j! @" D. I+ K7 C
+ {) s$ Z4 E0 S& V#参数存在$OPTARG中8 U' s5 ~& r: Y1 Z( _0 n

( d0 E, N8 H2 z8 H. Cecho "a's arg:$OPTARG" ;;
. L4 q; ]8 M1 K; Q6 Y: C2 z: U$ c; h: B) f- s% `" S$ W8 S  E  t& Q# B( M
b)
& e& O% i/ l6 a# c9 ]& E
5 h2 d- }% G. Y- u2 Vecho "b" ;;9 |2 o0 {' j6 j
; ?4 h8 C- D: k" P+ s7 W7 O7 ~' b
c)/ _* d, m# G, W* C# }/ i
. v1 {1 m, [: |/ g1 a: V1 b
echo "c" ;;0 E& K$ b: L- L/ Y- q' d7 U: ^

4 T+ s6 J, N8 G2 ]1 d/ _?)
1 Z; M8 i9 a$ r4 |# K& _" n
6 g# D/ o! g- ^6 y; _+ [7 _- g#当有不认识的选项的时候arg为?
0 i# u( l1 \# S7 L5 \  G( D# D$ R2 p) @- @+ r- J' w7 d4 U* d
echo "unkonw argument" exit 1 ;;4 s9 n. p5 J8 |8 _/ t0 A
" P2 c$ q7 P7 w+ O% Y+ s
esac
+ ]! ^, u: W( u7 L5 j  g: }& S8 X  t  M( O& }& W# ~, N
done
2 \1 j4 R2 b8 p+ @8 [$ M; z3 w' V* x2 W6 l; t
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
# h& H/ C- @( c; B  O
& k) P$ L6 G7 H5 N3 I( f来加载了。
0 M7 x9 i, @7 b6 y- t; j
/ ^8 q' O6 P! Y) S% o应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
0 c  }, Y6 g+ O0 C- A. a0 i/ ]. Q7 k0 Q4 C* N. }+ T
[vb]
$ n; K5 L5 c5 G6 g; [) `3 z  t/ f6 J#!/bin/bash# X: t7 s, R; P* f! z3 S; ?6 y
5 X) Y* y! x3 X& \' O3 `
# A small example program for using the new getopt(1) program.
( w# {0 u0 r; [' M* n# e7 F* s1 @8 D% H
# This program will only work with bash(1)
+ N' E: p/ x( a3 P4 d5 z
+ |4 D1 s; k( R, T, v5 p1 Q# An similar program using the tcsh(1) script language can be found
/ D" j+ O  _8 j/ n! |- h4 U! ?& C9 ^- K! `
# as parse.tcsh3 r4 W# U8 \8 O8 [6 |  }
# V' q) d5 {" G, E2 P
# Example input and output (from the bash prompt):
2 S3 b2 T* ?* G
- a  z+ D* ^- f  r# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
  D9 {" I% B7 J  D. b* ^8 s( P* X! C" \8 C9 V( K/ ^1 S
# Option a, u* p% P" q& K. l$ ^/ O3 a# C

8 z, o: @1 d$ U" O# Option c, no argument
0 h* A) o: |) ]4 M
0 `, p3 F4 c" B: @# g# Option c, argument `more'- l% H" a5 C7 f$ w

: A# {! Y' e2 N# Y! O" k# Option b, argument ` very long '
  ?% Y  \& {! j0 x7 I
5 D' T. e! U- u) P: G# G# Remaining arguments:: B# W5 p: y; r( G9 C
7 k* K6 o, K! |+ n" E
# --> `par1'& c% j  E6 }- Z) ?3 G
& P3 Y  l" N( ~  i; E
# --> `another arg'& H- @4 e1 p, L. B$ t
5 p3 V$ }: x' R8 i, Z
# --> `wow!*\?'
# p: g0 o- a  J9 g! q7 l; B5 Q/ i
# Note that we use `"$@"' to let each command-line parameter expand to a9 `) H# ]4 ^5 U$ O6 z: ]8 l

; R7 X# W9 F# Z/ D' |" ^" j# separate word. The quotes around `$@' are essential!# a# q! u* D4 i( l- j# @6 I, q* v4 V
" C5 @$ [" @- u+ _$ x& Q
# We need TEMP as the `eval set --' would nuke the return value of getopt.
' t6 @' x: l: w- z8 j: o$ g) p/ E. @4 g! f
#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
) Q* h" ]/ a% i; N  O; f1 k1 G/ H$ u
#如-carg 而不能是-c arg/ v% l& k! {/ h  I) B9 Q0 ^

7 n4 ^( X/ F4 N* b+ Z#--long表示长选项* t, Q5 i( h& _& y% \
8 m8 |) e2 Y, j, m
#"$@"在上面解释过! D4 C$ ]* i/ f5 Y! [3 i
' S# |8 ?0 }+ J, v
# -n:出错时的信息7 V2 M: F5 o2 ]6 g# v# \6 |
9 X8 s$ u5 w5 @* N+ J  ]5 A
# -- :举一个例子比较好理解:
5 l) ]( D* T+ d4 k- [2 d3 @
* q; K- _2 W+ y. |2 P# W#我们要创建一个名字为 "-f"的目录你会怎么办?
* f; `9 ^! Y+ E% ^, B; a6 A3 _) L# i' s7 X! K
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用1 U6 l7 u7 z  ]5 y) G- K. W

" w$ _" v1 P8 z6 X3 c( q# mkdir -- -f 这样-f就不会被作为选项。
2 S, }% |: L8 ]5 M* D9 Y" u: G$ T4 K: [4 c& ?" @9 i" c( {
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
0 I# J0 h* G- q- d6 E9 y* X$ Q8 F! W
: L$ E, e! l" \-n 'example.bash' -- "$@"`+ t; [. z( N8 S( d4 w1 Z: ]
2 h: I+ z4 L/ v, B8 m
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
0 P7 V8 U; {: ^* O# Note the quotes around `$TEMP': they are essential!) `" \# [& m( c0 f2 j

; ?* @& r- E8 v1 k#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了) ^" E5 g( G9 i
( N& K* d6 P8 D
eval set -- "$TEMP"
, ]' n& n1 y  A1 h0 G4 x+ G
2 y/ o6 c: i* N+ \" r6 q" S#经过getopt的处理,下面处理具体选项。4 P3 a5 n7 Q5 }9 E, E

8 M& w" N: H/ Kwhile true ; do
/ j. T& \$ X7 J: }" k: C! j+ J* `3 B3 n) s; V$ l8 u( H0 z% i. p! N
case "$1" in, V/ N" x, x9 @) z

- V) b7 T; j; D+ g9 p-a|--a-long) echo "Option a" ; shift ;;
5 E* V- o0 h" q3 q  I$ N, j  d. `+ ]" f2 D# a) y$ H
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
: x& W+ X' R6 H! \  E" S7 U, a6 b( c- Q/ S0 T& e6 Z  B4 {3 y" B
-c|--c-long)- c0 A* K( T; Y- D$ Y

0 v/ r' m  T# K. e3 \0 f  I# c has an optional argument. As we are in quoted mode,. ~! R$ {; R0 c& p4 u# }

: G7 l3 W4 y/ x; R* n# an empty parameter will be generated if its optional* X0 {7 q6 e0 W2 A7 B5 c$ b

% Z( N  S' Z8 u# argument is not found.
) O/ J- V# w# ^3 y5 j' a, ]6 ^+ _2 w* \! ^" @' J/ x
case "$2" in0 _+ i3 f. x2 @

0 n* Y. w5 `* l1 w"") echo "Option c, no argument"; shift 2 ;;5 I" W: C3 q$ b6 J: c

' y; @! k& v& W2 g' F  G*) echo "Option c, argument \`$2'" ; shift 2 ;;. m. V; ?. t# @+ f

& C0 G: `# R% u3 A$ P+ a" y3 qesac ;;) }( T/ a2 n( A
/ `9 a% ]6 U* |" t) M
--) shift ; break ;;1 p* M# Y- ]" ^5 |8 m3 A

# L- j' S; k( g6 b) M*) echo "Internal error!" ; exit 1 ;;$ v) g4 h6 d: s( j/ A8 D: x

) ~" r( n9 i5 D8 Qesac! d, c! S% B3 F- c6 x7 \$ A

1 w! M1 E# g- p0 J* vdone
7 d. q- R2 W# ^4 Y+ V6 M# @! F( T* L  I6 g) P8 V' E4 I6 R
echo "Remaining arguments:"& n# c% d0 G; j0 g: X5 u- k
4 N* s& y( R: s: U& T: H
for arg do+ t' W$ s' f7 x) H; b# z
4 U& s$ w# N: g( T6 \& z* U1 L5 a
echo '--> '"\`$arg'" ;
0 }) p9 w! y) J6 g" i( q4 e! t8 d! b8 x
done
& X& `1 v( g& _" S$ F. X  X6 f
) f& T7 p6 Y( @9 ?9 h1 i
, \) i2 s# s. d9 z3 v; ^比如我们使用
1 |! `( P. Z+ O! M
7 `- u# Z! ]+ e8 D2 V8 l" [./test -a -b arg arg1 -c& w" U' a# ]- h0 C7 y7 ]
4 K, M* h" A1 m9 e, ?" Z! j
你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:/ o6 t1 `/ F- l. h" X8 A& h! @

, \. E: M) |2 `3 w6 `  U+ ]( ]-a -b arg -c -- arg1* g- {5 \: i; v: z

: ?4 e5 b& |6 S, {+ ?) d8 l, e/ }$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
# E# ?! O5 q9 s9 D! B* R; V: @
$ ]6 a7 V$ i6 v5 K, `9 d+ y3. 总结
5 t. c6 D* V1 c: W  n# ~3 v; L, m  q* C; H: S
豹尾。: T  ~5 b" F; `( f7 v
8 Y6 B1 j7 }0 G  d! h
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统4 Y& Y1 W" l/ X5 h( P

6 C3 b# @# J3 x$ O" d4 H, d
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
* L" p* }% U. d! w. \记得getopt常与shift结合使用,while循环一下就好了。

9 u1 `0 L; H2 q, W$ u请教一个问题
* \3 k. T8 I7 A$ ^2 N. }! ]# S1 [( v有一句 :set -- `getopt -q ab:c "$@"`9 X0 |, d* K1 I0 B2 \% Q+ h
请问 这个如何解呢??- C/ P5 N# y7 {8 Z+ @
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句
; A' S5 E- l0 Fset -- `getopt -q ab:c "$@"`
. y' Z. L! M" |0 {" u. o& T  Q8 Iwhile [ -n "$1" ]
! K* i2 B2 g4 H. ado
& h3 U, E- |$ [* S& f. J  S8 |1 H0 M  case "$1" in
% U+ Y" k8 C* o# U( L, P4 r2 [- z  -a) echo "Fount the -a option";;
( h; r1 }  z: Z" @* L- B6 S# y# Q3 {
  -b) param="$2"
; U% ^! Q6 z5 i: H3 n1 }- x      echo "Found the -b option. with parameter value $param"; P4 n- y4 v3 h5 W
      shift ;;' _0 Z/ s: V0 B
& `  C" A; V, _) e
  -c) echo "Found the -c option";;1 \1 {5 p; D$ u+ b$ N8 y8 d# \7 L

# N4 t% v8 Y8 J5 j, m% D  --) shift7 C, z' G: E+ r& c
      break;;6 A$ |) t# ?" k, O% n  Z6 A
1 c# ]& ?2 e& s! `$ m2 m
  *) echo "$1 is not an option";;
9 |8 B5 O& N8 ]( J  esac
/ Y/ t* J% X/ V# u% W) c  shift
) |! g9 N2 d  \# c1 h$ W: m  done$ Y% f, x5 {$ q2 ]* Z" G1 z

9 R! c7 a. T* k3 d2 y9 U5 z: I  count=1
& l/ j' C! B2 a% t  for param in "$@"! g! V4 Y3 K6 c- k# X6 a9 A: L
  do/ ]- M1 O/ ~  A5 N. A
    echo "Parameter #$count: $param"7 W  n; f! R+ m1 ~- ^: k5 |9 \
    count=$[$count+1]$ l& b& O4 d) |5 Y9 `
  done
1 d* l, h" R, k4 z! ~
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39" s# f5 X2 w' p
请教一个问题
1 }- `* B& W/ g. N# A7 P7 }& L有一句 :set -- `getopt -q ab:c "$@"`; u( s( S; L% f0 p: O: A
请问 这个如何解呢??

+ p5 n# V" m& b3 m! o: z) a! M请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
: F; `: e; M4 r0 z: M( E
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
( H* L+ ?# }5 M9 q. g; E请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
! u( [) Q. Z$ D, n0 V* j4 H# C
呵呵没关系,大家一起学习呗。
/ ^9 Y( Q+ Z% {% o$ f经过一晚的思考,我发现了之前我看到的一个语句:set -- -F
5 o4 Q2 d' w) o, a5 U# I' v  t* t一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,$ F2 A1 M; S8 _; L* {  V* i% [; X3 g
所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
5 P6 s4 f7 r5 ]' h, ^! b) K如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--
/ l1 r8 H. b6 K# a5 ?- `0 U$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。" ~1 m9 I" E! X) B, M, W/ t
补上昨天调试的代码
+ \1 F9 @. e6 U( K* N. g
. g2 T; W2 A' q9 I! l' \) b#!/bin/bash: N* j( _: p+ L. |9 T2 @$ Q
set --  `getopt -q ab:c "$@"`: a# W/ T$ _% ?7 d6 @/ [, H
tt=`getopt -q ab:c "$@"`' J! G( W  K- {* P' \- E& S/ D
echo "\$tt:  $tt"# T4 l# V3 y$ l9 Q& E4 w! {
echo "\$0:   $0"& t0 I" w" p5 C* ]. C6 |! `
echo "\$1:   $1"
4 o) B3 Y% ^5 oecho "\$2:   $2"
. r9 `) T! `6 c& h: Cecho "\$3:   $3"
. g5 n$ \* ^: i( F  @5 xecho "\$4:   $4"6 n- m' k. E2 C: ?  p8 `
echo "\$5:   $5", M* l( s2 [( r( I# K& w0 P
echo "\$6:   $6"0 i( G+ A1 [; n4 e- o
echo "************"
# W8 c+ }" N  ^  S- m# G* }4 M* J2 O2 w

% O. r( f! L6 S% K; q8 x1 ?- N1 j$ J; n$ v7 p- \
while [ -n "$1" ]4 Z5 o" @0 z0 S( t6 N  @1 x
do) ]1 \' u0 j/ j1 D2 c
  case "$1" in0 `: E0 E; B1 a: a) p. w  s; v
  -a) echo "Fount the -a option";;) B8 [/ W+ X3 ]6 A9 _

2 T) P0 w+ @. `  -b) param="$2"
# S& h" s: @& p6 c$ {/ Z      echo "Found the -b option. with parameter value $param"! s) o9 e; f6 ]
      shift ;;
% V) J, k5 x6 F* [, b3 x2 m) m  Z/ Y- ?, g! v( r! `8 S
  -c) echo "Found the -c option";;/ b! Y5 G. W; {, M' w. a- {
2 S1 y4 g* A- \. ~. O( ?& p$ P
  --) shift
- d( D# |! ^, Y8 f9 x8 d      break;;  M& i8 E. Y# K7 }$ L# w

* y3 U+ T3 u5 G6 w4 f- e  *) echo "$1 is not an option";;. A" Q5 O( @5 E% t
  esac6 j2 t% z" `: n1 |+ K
  shift% G4 X' a* |* s3 s5 g  N
  done
( B  L) Z# ~$ [
; x9 Y4 I2 Y5 ~, g0 j  count=1
! U) _$ n3 F. n! Y4 y! p2 a  for param in "$@"
1 x, {" l" r" ~) [  do; L5 h) D4 E! y* z, O9 X
    echo "Parameter #$count: $param"
7 l$ e/ N4 M) a3 ~/ N    count=$[$count+1]& u& ^7 s' ]" x+ N, {. [+ T" P5 s
  done' r2 u3 f# M- H

" {9 O9 Y' S9 e3 W1 g  |( b$ p6 [/ ]/ p+ e/ R4 }7 Y* Z
) }& o* N  k* \3 C! f& D
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test
& F9 Q- E8 x0 q4 p: {$tt:   -a -c -b ''\''test'\''' --
9 a1 u* `/ b; k; q0 O& g$0:   ./getopt.sh1 p, m" `, \% J+ ^  I3 W$ x5 {7 @3 A
$1:   -a
, h* U" u5 n+ V# Z$2:   -c
( ^- u. y6 N9 v, v6 Q$3:   -b' s7 {3 J% J" d' F9 Q) a
$4:   'test'8 y6 ]  I; K8 a, u9 a
$5:   --- }& k$ A& ~# g" T& X  t2 k
$6:   
4 [  l4 B1 ^  e4 _( S( _6 g5 O$ j************. `6 s0 _2 m: A9 L
Fount the -a option) O/ y; z9 y# f. E  ~
Found the -c option* L/ n- A5 N1 w1 N/ }+ n* Q
Found the -b option. with parameter value 'test'+ s5 P0 A$ d# R! Z% y) K
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法0 C) a% c4 h9 I) a
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
7 C1 _8 L+ p1 ^( K7 b代码:" }- e, i  l* N
while getopts :ab:cd opt4 K8 M6 G8 {% T
do- n! v& y1 \6 _
   case "$opt" in
7 A& g9 Q) T, x  a) echo "Found the -a option";;
8 Q' Y3 D( b& q( X' `  b) echo "Found the -b option. with value $OPTARG";;; |6 n. D  `# S- }: n; v) Y6 Y8 l
  c) echo "Found the -c option.";;
& }; `* C9 o* p  d) echo "Found the -d option.";;
7 r3 I) I1 i5 Y. |3 A  *) echo "Unkown option: $opt";;$ I) [9 v' P. V6 N5 }
  esac
! e/ [  D  V9 h! |: udone
% j1 t. c4 E2 V0 Z9 `: \shift $[$OPTIND -1]6 U7 V$ ?& U; i5 x- N' @
0 |8 ~0 r+ ^7 h( u- e4 a! E( l
count=1  J, x4 e! W( f4 ?5 Q, S& G4 M8 W
for param in "$@"
% ?# n5 R: `% D+ O6 ^) |do
0 B4 x% S% F5 O# E# O" F) ~! u: h   echo "Parameter $count: $param"% \1 m  B$ D+ p5 c" ]3 M! S
  count=$[$count+1]
; {' S. y1 b- K4 c2 c0 m1 r7 Zdone
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。# o% Y  T5 C( t
其后就可以这样用
" t9 Y8 f' C; D! [3 Y./getopts.sh -a -b test1 -d test2 test3 test4
, W: l. r# ^$ U5 t, }./getopts.sh -acd -b test
4 ]. s+ B9 G% k; [./getopts.sh -a -b test -c -d test1 test2 test3 ( e. D( a/ K6 j
等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash* ~/ P: [7 |( j1 J

7 _( j; F4 B" p  ~$ H
- U; D' [* I7 Hwhile getopts :ab:cd opt( b! X! z0 U  [9 ~! q. D( q2 N& Y) V1 m
do
' a% k) s/ A* @: m$ m* |( ~% `: f1 [: \  case "$opt" in8 e+ O7 l, s9 X8 v
  a)echo "Found the -a option";;" e( D# Q2 R# m% y9 S! e  d6 b
  b)echo "Found the -b option. with value $OPTARG";;
; ]- X. _% O4 {# R  c)echo "Found the -c option";;
. u$ N8 ]6 d' H# k* R3 X- o  d)echo "Found the -d option";;
7 \5 r5 ~, K0 H2 t% x5 X$ ]" }  *)echo "Unkow option: $opt";;
5 \! @5 k% z) [, K  esac' a3 I! Z6 I2 W1 ~# [, j
done
% b+ ]# t9 F) P" C
- x' u) Z" z" p# }% n% n: e echo "**************"& t" z* L& e3 x/ h: D
echo "OPTIND: $OPTIND"+ R" N2 r5 @+ q. R9 U! z
echo "\$@ $@"
9 p5 {0 F% j! _' x shift $[$OPTIND - 1]1 q* n* F8 r3 Q
echo \$@: $@
8 E' ^3 p( i) q! p: T: N2 s echo "**************"
9 a7 |! }- u' n4 P: e8 y- |. w: k1 R+ f0 N' w  Y
count=1
, i2 C) r. g$ U7 S0 Bfor param  in "$@"
8 z0 ?& ~5 ^, ~. |6 X" C: ]2 O! Tdo
1 ]4 ~% M/ L1 H  Q- ?9 J  echo "Parameter $count: $param"" F! ^7 B1 h. a  w1 A& U. E9 q! s
  count=$[$count+1]- Q; p+ Y  U# {5 u3 ~+ L
done
3 {7 v+ g" N# U: C
6 H: N3 n# O6 l- C. v( D# Y4 P
1 Z/ A9 Q: |7 D4 K! {8 \4 z; Y* F$ X" W. y" y4 ]# g8 d5 ]
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
5 W# D, n! A# }  t
4 ~7 k! N2 r  `  C: ]
回复

使用道具 举报

本版积分规则

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

GMT+8, 2026-1-12 00:44 , Processed in 0.040696 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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