一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 4162|回复: 9

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

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

% }, G9 e. E/ d1 W: K9 J  jgetopt/getopts:Bash中命令行选项/参数处理9 @3 A! F/ ?8 t' @6 F! s0 b

1 W; z1 v* S( V+ a$ \0.引言
% X  }0 ]/ S1 C( ~8 z4 T8 _5 L1 z) t; I  V' O5 o+ _5 a; E
写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。( R; P6 g. Q4 x3 M% c$ u# M

3 I) Z; }) y6 `+ z5 Y7 L选项与参数:
1 U6 M  @8 u9 n/ z) C2 i9 w+ z) g
. m+ }4 J3 H. l# g如下一个命令行:' e* F- _: z$ [

3 D4 u' E- `. c/ I; P[vb]9 Y8 u! a) z3 N" \$ d( _0 F
./test.sh -f config.conf -v --prefix=/home3 E6 ?% p* w  ^

6 h2 ]. \4 ~7 c7 |  |6 _+ ~7 K我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。' v7 n9 m: K: B+ }
4 X0 p- T" c  B% v
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
# }- {1 Z7 B2 L6 _! K8 u: E
' a+ p8 Y9 p  e% c5 m3 M/ G( R在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
! o( O- ?8 f& N" B* U- i+ K, _2 h' A# }) s: ?
手工处理方式1 O) [2 @' w( i) x! R+ s
0 t( _4 I$ h0 Q1 q
getopts
9 [6 C5 O3 u2 D9 L( R2 b5 [* b% O
+ {6 h3 t- H6 K: y$ Lgetopt
: S6 P8 J1 V2 |. C- z% l, n- \
5 ~8 L# a: E7 V& i0 C: E下面我们依次讨论这三种处理方式。; n& [) a3 N* C% k$ U' l( @

4 P( p1 y& x6 {9 G6 u: u+ r1. 手工处理方式
7 O% [  z5 u! b+ x- O  M2 u# U, f! A4 ]
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:, G5 c/ u- m- ?/ ]6 U  K

/ D2 {' v5 B& N, E$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]  M6 [% ]( s1 o# g0 x$ b2 }* ^
$1 : -f,第一个参数.) z, x1 D9 ?7 R+ y, }* \

0 o0 m9 H8 t) @4 o$2 : config.conf
+ ~, F; }( Q% |+ r9 s- d8 \) y  M9 q% ~) ^
$3, $4 ... :类推。% y6 K# L$ y5 G! n* r+ U. _1 a3 Q
. j* h5 }! V5 `/ ?1 I6 N3 H6 ]
$# 参数的个数,不包括命令本身,上例中$#为4.  l& M* h- l% w4 g+ Y. Y! G

/ ~$ B& m/ ]3 I$ D7 u' d$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home& {. b8 z* Y% w2 [, N. C6 W& F

! j' g) S. o. y9 o5 c/ R$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:' p" R! U3 U5 O; m
3 Y0 _# h8 m8 r, p
[vb]
4 H3 i& t' i. p- d$ ?( W# g#!/bin/bash* L+ K/ s4 M% y- h8 C! m7 n

8 y6 @$ I% c' f! m8 F. ~for arg in "$*"
* k, ?1 L* G4 q/ U+ o& A8 F; }
, q1 O6 K2 y2 _7 \! c3 r9 S8 S4 M0 Fdo
! |8 k# C1 H4 f4 \
! Q$ q, [/ e/ N$ \$ [" Vecho $arg
& h9 G- X0 L" ~; ]' n) @4 l6 ~0 a$ h8 ^
done
9 w) T7 K( f  z
2 n: t! y- A/ t1 Gfor arg in "$@". _  \; p( Y2 y, ]6 V1 f1 e7 S2 Q

: S  w' I& E3 W6 T; A; k& L; edo
" c! e' y5 q$ B: f3 e; e( h5 A7 |
echo $arg9 M. X+ A) ]0 R7 ], y( }3 S, V2 x9 ~

  q1 L/ U. x9 c0 y) A8 Ldone' V( m1 A/ u1 N# c5 Q9 N7 V. v/ ^6 u

" I$ }. O' p  g9 ]/ C# Y0 N执行./test.sh -f config.conf -n 10 会打印:
% w/ S' K+ ^+ n1 E
+ d1 I+ L4 ?+ m- R-f config.conf -n 10 #这是"$*"的输出& m4 a+ S1 k; H

+ D) i$ U4 W6 V# M/ N+ a#以下为$@的输出
2 G9 s- T0 m3 M
; w* Z2 G9 V6 F2 q% H1 ?-f
+ g$ \3 Y& T8 c( v* S& ]6 D) p- _8 K# I# Y0 K, `+ t1 `/ _. T
config.conf
/ J$ D" b" P4 ]; ^. v1 }6 b/ A* J6 }6 m0 D. u: D$ w
-n: U* u- P( C1 L) S, J

; q" T3 i7 g. J5 S10
0 a' o- e2 |( c: |7 w' V! L) D1 {/ ~' M1 [* d
所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如, D# {: @  T. T% F
+ }" M: `  `5 y9 c
“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
% r+ f' ~1 y" o) Z
/ i# @6 W* R: Y; Q[vb]
& H' [$ E; X( W#!/bin/bash
/ q# [2 e& b, C% v! l% S% f% _9 g# ?9 G. V6 `6 \
#if [ -n "$1" ],参数不为空
) j% F# ]+ g1 q3 }+ x4 j  Z5 rif [ "$1" != "" ] * F( V7 v9 A% U0 z6 j' @$ ]7 Q
then
- w5 `$ d2 j. t2 d: `% c/ h. X# z" l, g4 U( x
#...有参数; [3 p, a* M! K/ n, c1 C+ S

" l5 s* j+ s7 Eelse0 R! q" X0 i- L! Z3 j; j4 E% h

+ F! R& B, v4 h! w" z8 c) M) athen5 C1 Y! v' D' f+ l, [$ V

1 P# D' F9 d" k; S" D#...没有参数& T  g/ V7 k. ?! W* D# v- k8 H" a
7 O3 x1 i) f$ R  I4 @
fi: z$ ?6 E, }  ^9 T/ C  L
2 D! Q& b. \( E+ t) _+ O- [% H
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。" v* l' h$ g0 a% e7 T3 W! T6 r8 c" S
. Q( q6 g8 C3 }6 B' l
2. getopts/getopt. m+ T" ^& B! F# c( B/ y" s

6 e; E* j4 u5 _8 u+ u* ?5 g处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:/ {, \. k" M1 z0 z0 |) e. G

' w3 h# W3 i0 y$ s8 |9 c: @3 G./test.sh -a -b -c : 短选项,各选项不需参数) O( s5 g% R# i4 S" n( B- ?
3 L0 i0 x  X$ K% M" D! A- ?
./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。" e2 h0 L, B. H
) r; S6 E+ e+ K3 d
./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。* e0 R4 D& R* x8 h9 u6 H

- ~% Q6 @" M# @9 t' Y+ p. ^/ X$ G./test.sh --a-long=args --b-long :长选项
% A0 b& ^& q% I2 ~* X0 V
0 [7 ^( O0 T  S( P4 Q4 }我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
4 `1 `* p5 H4 f  U# [
+ k6 ^: K' m3 Y# _, l[vb]; N- R1 ^5 s; }3 _
#!/bin/bash
  k' ?. x) f$ r0 `
  J6 B9 J, O; r4 L) o6 B#选项后面的冒号表示该选项需要参数
4 |. s1 H1 ~  j1 S; M  t  M& f
# u+ U8 T0 X* y3 V& ?; ^$ W; Cwhile getopts "a:bc" arg& [2 D) ^* U" @

6 U1 b( K3 j: l/ x+ v8 k# }$ ^* fdo
4 b1 b6 T  }# U! d6 B7 F
- q. a) _' q8 k4 l- z* i" G( Rcase $arg in
! I5 `, ]: R- `( ]  A. O, h: @' S' r5 t1 E( }1 I
a)
1 d; E5 _- Y+ u( ?8 G; I! m9 O5 T
#参数存在$OPTARG中; z( J( A7 f& G* M5 S

+ \5 g. \5 `. X7 F. B/ s) T) v& `/ [4 uecho "a's arg:$OPTARG" ;;* D0 ?' J4 N/ }) D+ k# w
6 }! n% @; w5 w9 ^5 ~
b)$ x* S) k/ ?: ~. I' ]
9 l$ q2 F' T8 [: f) \' y
echo "b" ;;
- b, P, B: q6 \* ~6 g7 C1 V4 u4 [! Z; @( w
c)/ W( Y* N1 ]- L+ j2 q
) S. p+ N1 Q, c: R) J# V: z
echo "c" ;;" J* l$ O5 y( y+ D
. K7 t* I5 l# Y: J; r. V
?)
3 y# G1 L5 R; z" r4 n; N
# `, y/ g1 ?8 h% O# \9 R/ ]0 I) {#当有不认识的选项的时候arg为?' d, n3 O* @. C
5 G+ `  z2 V  c2 q
echo "unkonw argument" exit 1 ;;
! a% U9 i% p: r1 i+ \1 O  k# V9 Y7 @. A/ U7 E3 Z
esac
# e) j( B) q. T
; B+ f. ^: o5 [3 @6 S* ~) ydone
& z% l; A4 r$ p" ]
" P- B7 b) V! e' i* K+ A$ ?% F7 o$ g现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
+ @5 x0 j0 s% p9 N7 ]1 [% p/ g
. D7 c) P# D# R. D9 ~" ]来加载了。3 p0 ?6 t7 D$ A% ^4 N3 Z' h# B0 q
' F  d$ J( }1 {; M# a4 C" `
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:7 |5 p5 K2 j9 p; M
1 q( i$ e! B, c& o
[vb]
1 c% k! @! a+ t+ y5 U3 f$ h6 H3 Y#!/bin/bash+ p$ [! ^' ^  a$ V

' M7 x  `9 v  F# A small example program for using the new getopt(1) program.
; }7 H6 m# B5 W9 @
- v4 p" a' f9 c, C' m& j7 ]# This program will only work with bash(1)
, @) {' X# T( E' L
% w4 J# w. D6 J0 r# An similar program using the tcsh(1) script language can be found
" x: x6 ^( M7 w: Q( x" @' b
* ]) {5 [4 q) @+ r4 V# as parse.tcsh
1 k/ l  J* n+ u7 [( ^2 j4 H: W+ t. v
# Example input and output (from the bash prompt):
% Y. b0 {$ m1 A+ J/ ~$ G" Q" S
! K/ o! F, a* c# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "  N" `# N) {0 u, U

- ]* `3 l' O( |( e" \# Option a; w9 }: i) ]; U5 X% |4 B8 l

  p$ K9 v6 L- n& q  s( D# Option c, no argument3 @: r) ]% i7 m% R3 @( g% D
! n( u3 b0 i7 D+ j6 m- x: w5 D  P
# Option c, argument `more'
6 }6 F! B  v3 p9 {3 I' Y' _/ G; [# c' M" i+ N) D
# Option b, argument ` very long '
. l) V/ t& H, J& T5 Y; g  o
) S% Z$ r! y% r3 U# Remaining arguments:
( ?" g& @& B) j
, ]8 E! d+ x  x# --> `par1'& t6 p1 B" i" X; n- R
( y6 r6 Y1 U% w4 N
# --> `another arg'
5 I0 Q1 {+ W& m: H8 p/ m& d- b( b2 ^3 c5 C
# --> `wow!*\?'
( N' q& f8 e9 L1 s# s  Z3 T# w% O. z! G+ m, u  U- Z
# Note that we use `"$@"' to let each command-line parameter expand to a1 O3 f8 q+ \' i, M( |% i" H
7 C1 I5 {, \8 K% T4 Y; p
# separate word. The quotes around `$@' are essential!7 E+ u$ L' a6 z, [- b8 ]
! ^0 `* B/ g% c% ~
# We need TEMP as the `eval set --' would nuke the return value of getopt.3 |# @% h5 r& m9 q3 r5 i( q" a

% ]/ @6 i1 ?6 Y* r& c5 J% ?#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
# O8 ^- P8 {2 `/ e, b6 `) E
: h# a& ^  h+ {7 K5 R#如-carg 而不能是-c arg
% S  ^7 x5 L9 o, n
0 d% R: ?5 O$ ^  B) G  V, D#--long表示长选项
5 K' y: j+ X: \* p, Z
0 ^1 l0 D" X4 G# p3 G#"$@"在上面解释过
/ w& |9 B" @6 H! _; x+ |2 x8 v9 b2 X0 f7 I- K8 v
# -n:出错时的信息
5 U8 `0 g  n3 j5 H5 B( V, x. ?1 Y( D3 P; T" x2 c0 g
# -- :举一个例子比较好理解:* U: ^$ u7 z, ~& B
; C3 a" n( A, ]
#我们要创建一个名字为 "-f"的目录你会怎么办?
& f0 ?! P; Y0 N' Q6 I' l5 m( t' h. c+ y
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
4 }4 m# X8 }. c; O% I, N3 d
$ \: v+ i1 V: K" t  i# mkdir -- -f 这样-f就不会被作为选项。
! A4 O2 C: v& ^* C
& b7 @2 E1 u& m* j8 t$ k3 nTEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \6 Z: }/ s# J' ^( O

- W" y9 ]# u& h. j1 h5 ^" y  I-n 'example.bash' -- "$@"`
5 i* v( P" L2 l3 e9 \
7 G( s+ x* {6 p- P0 yif [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
* M9 H& V" f  f1 e- H# Note the quotes around `$TEMP': they are essential!/ a/ t: W7 h- g8 @( m
- x# A& O% ^; _5 a9 X
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了- `. Q; H1 b" J& u0 {1 p

8 O1 i& c  H2 ]2 meval set -- "$TEMP"
1 F$ ?- H$ n, X, f' H+ N' [; Z8 |+ s+ i/ |, v, a
#经过getopt的处理,下面处理具体选项。2 ^" n9 `' N$ k& D
+ u, Y% t6 f  i  _! D  G
while true ; do
  \1 F+ R5 y: \) T' x/ O9 x8 V( |) U8 {' h/ w% }' X+ s
case "$1" in& c* |( ^& Y4 j+ g# W

% a* C- b2 l6 C0 u4 f$ Y-a|--a-long) echo "Option a" ; shift ;;
4 x/ I& z- P$ B) d5 J3 Y/ m9 `4 H2 |# Z9 X! S; H
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;" a/ a% I0 O; }8 L

( q, e; o3 W2 H& |  y) B-c|--c-long)
1 t- d* ]* r: U0 C6 |" D% d
+ {6 V9 Q- m3 u' ~# c has an optional argument. As we are in quoted mode,
7 H, X# }4 @7 c" u( M& c7 }' A8 @9 B) k7 O& k7 W8 |
# an empty parameter will be generated if its optional7 H6 R5 \1 C; r' z7 ~

6 w. J  T1 c7 z9 i& q+ m. C5 V# argument is not found.7 V  }/ h; _- Y6 O" I* [3 _
2 k) E+ w* C8 u' f' ^' f; E
case "$2" in/ p! j8 u3 |/ ]) k# U  t. E. A

: G2 T' W$ e1 O% ^  a"") echo "Option c, no argument"; shift 2 ;;# J1 ]0 _5 h6 L4 H3 J4 D6 w

$ |, U6 B) h% `" S3 K3 p*) echo "Option c, argument \`$2'" ; shift 2 ;;
6 p3 }, D: O0 h  z
" m9 p- O, ?  a( g, v- i/ Desac ;;
/ J' b! v% _% S2 f  ~; ^$ T7 t
  O4 g- A  G" w; d. E--) shift ; break ;;6 Q1 [$ I7 `% d
1 m. S0 P0 h# H
*) echo "Internal error!" ; exit 1 ;;1 T) r( ?- J3 o8 l) t" D
( w/ h' G" C+ X, x, W2 Y
esac
( ^. I5 ]) ]) S& l/ ^  r/ q
/ t1 D1 g' ?5 ]$ n1 G6 C+ b9 b4 |done
0 a, z0 T0 X$ P- S3 Q; U
/ h; b/ |2 }& q  R9 e; v4 G1 Cecho "Remaining arguments:"
$ b  @9 x3 n& s; Y. `3 A
6 F0 H3 u, {' ~* x6 wfor arg do3 W, R) b, t9 B7 f( K
7 x6 L& |" n' P8 R$ T( }
echo '--> '"\`$arg'" ;8 ^1 X# f  j9 {8 \  `6 X0 \! L
" D3 ?* W+ c# e, g  D
done
; C: \3 m9 A8 H( @, `# K
. X" S3 `, K( j+ I" d* O
4 p* g1 Y( O6 k4 \比如我们使用
* C. G. D# [6 b& W+ E; U' a7 Q7 {! N* E8 q: g- p: u
./test -a -b arg arg1 -c. O9 |8 W: y" H/ u% G2 N

: T! b% ?! R* G: y$ R& W" q9 z0 _你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
% R4 W" a  P' H) W5 C
. U$ s7 Y( U+ d' |% r) ^; D' E# f-a -b arg -c -- arg1
% C7 `  Q7 J  E) a% U! |3 X# c! _* k; V% k2 [" Y% \
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
7 |2 W2 A$ f: E" c& j( O0 {1 X) L6 s: N
3. 总结! |! K" b; Y5 Y$ q: D( R0 M( K
4 D- N) @0 b( I- `1 g+ ]. Q- p
豹尾。
; Q- T& x; B( ?3 a2 q; m
: R9 Q$ q4 ~1 @# |# V. |本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统0 U1 y/ K1 w1 {$ L9 ^( C8 N* F# a

, A: B  l" H# |1 |# s( j1 I9 X
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33) N' z5 Q4 h5 _0 y- d& I
记得getopt常与shift结合使用,while循环一下就好了。
& i9 u; I5 V  t
请教一个问题
; U: M" ?' B$ ]. @" \有一句 :set -- `getopt -q ab:c "$@"`( ^9 \6 f! N7 q. a& R
请问 这个如何解呢??
. X9 L5 }5 g5 w" r/ K3 i: p
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句5 T/ U) j1 i8 E2 y
set -- `getopt -q ab:c "$@"`; A! s/ a2 x5 m
while [ -n "$1" ]8 T- u( F" B  i- s% e7 O; {
do
9 ~4 b4 u' `. m3 f9 j  case "$1" in
5 ]0 c1 f0 [. Z) s1 J+ D  -a) echo "Fount the -a option";;! A  {) |' i3 o8 x2 t7 R
2 Q# C  _( I: x4 g+ ^2 M; G
  -b) param="$2"
! o. `. `( T) d0 W9 |+ j      echo "Found the -b option. with parameter value $param"
3 @0 V. a7 j" g7 J' k      shift ;;  a5 ^( ^4 B  a1 q7 Q# E

- S# z& `8 ]. O5 |  -c) echo "Found the -c option";;7 t6 g" e$ g3 I7 T

; p5 L) J/ A5 s4 E: y  J' d  --) shift
5 g' X+ S; f5 K, K      break;;, C9 f- X" X: H  ?

; s6 y/ `) Y7 l& X  *) echo "$1 is not an option";;7 O0 B. e2 E2 W( x
  esac: _" v* k6 B& r( T2 s  ?2 i
  shift1 u7 U+ |) l. F- a3 ^) ?
  done
1 ^# O( r+ s% B% H / e, _7 ~0 Y/ U$ w- y! r5 m
  count=1* m& H7 A0 T" @1 |: ?  R
  for param in "$@"5 r( M( ~3 [' L9 }, u8 S- I
  do
; _( X+ l' Z3 L0 Y$ n/ M8 i    echo "Parameter #$count: $param"$ G4 s- N8 d' s# ~
    count=$[$count+1]
# `% f& d% p% Q1 }; A: Q  y% i  done/ K$ N' ~: F+ p3 L$ g) W
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39: X) m( x4 H1 l7 Q# P6 Y& P
请教一个问题( r+ X% x+ d% L/ [) j3 @! Q3 ~% J0 W
有一句 :set -- `getopt -q ab:c "$@"`; y3 V6 s9 N' @2 W4 W' n" @# @
请问 这个如何解呢??
2 X6 t0 Q1 O: o8 K* ]
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了, o# e, u, E" H( }! ]- s: n4 R% X9 O
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:127 z& o: U0 l+ L3 [
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了

8 v* _- p; C- e0 E呵呵没关系,大家一起学习呗。
4 _0 L( S0 x6 o) g& U( Q: J经过一晚的思考,我发现了之前我看到的一个语句:set -- -F- p6 {- B! j! ~2 D5 d6 ^( T8 P( @
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,
( Z! x, y, a/ q. ?: l  l所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
- O4 o! j& y  ]8 h如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--# Y* u1 R0 t; ?
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
: f3 w3 ?& Q7 }' V补上昨天调试的代码
9 @! M; t0 ?/ k( W: {9 k) r- V
1 y3 `9 n& n& t#!/bin/bash6 o9 Z5 k/ |' [4 M# A( s6 t+ ?' e
set --  `getopt -q ab:c "$@"`. B6 @6 P5 H4 u" w5 X6 O
tt=`getopt -q ab:c "$@"`( M2 L* ]( ?  m5 l0 m
echo "\$tt:  $tt"* h0 H) t* a5 _  ~; [8 `
echo "\$0:   $0"
& h+ }1 x2 h  ^7 \echo "\$1:   $1"
" @- t, B& {, ?* {/ qecho "\$2:   $2") U( D# N6 V8 Q" c, S2 @! `7 ]
echo "\$3:   $3"3 H& e+ f$ R+ O1 H# A
echo "\$4:   $4"( h% r6 E/ `( j7 B( x. j: R, b* P3 c
echo "\$5:   $5"8 s2 A! [/ a$ q: A- m4 u5 k8 d
echo "\$6:   $6"
1 z  o4 s/ `4 n6 hecho "************"5 |- F& r  V1 i

5 D) I+ x) |- Q( X- V$ Q8 {4 M2 A- ?3 x8 w- L7 q

+ W4 I. a  I+ M/ z& q1 vwhile [ -n "$1" ]) L8 H; A  L% |: b/ X( ?
do
8 q) Y7 V3 w+ K# K8 D  case "$1" in
- }% \' O3 l: [5 S  -a) echo "Fount the -a option";;' I3 {; u; ]+ D( {
, x1 \( {4 K% a0 Y8 Q/ e- b/ H
  -b) param="$2"
* T, o! z: n$ y& [0 @      echo "Found the -b option. with parameter value $param"3 M/ c9 H* @$ {# r& s1 Z$ ^$ J
      shift ;;9 _( r2 M& q1 i( W0 a) j

( |; L) R) F) i$ ~  -c) echo "Found the -c option";;0 E1 `8 \3 }) e9 i/ P+ R; H! G
. B" x, i6 H2 o# l% s
  --) shift
/ E, p+ W' n+ B& P$ p      break;;. p; P: B  ]2 F4 f5 t: g
! W  n6 K5 B& Y! }# G: ?* \  v3 u; ?+ q
  *) echo "$1 is not an option";;
0 k9 Z7 }1 r2 P! @  esac% P8 M7 S; U6 `3 T7 L$ w
  shift! _  Q: t( |" k+ D
  done
3 g3 G& l' G& b7 `, B: J0 P4 \( s0 p9 F2 H7 p
  count=1
+ H5 Z9 ^% {6 _  for param in "$@". W& x8 J3 b9 t# J/ P% C
  do, ?$ r$ }! h" V3 O; i* y+ y7 V* g. T( r
    echo "Parameter #$count: $param"
3 A" Q3 Y: C7 ~- z4 ?    count=$[$count+1]
, r) A8 z) N( T& Z  done
" Z$ Y* ^3 @+ e% u* J+ @- Y
7 w, q! _+ K: z
- b& F. x- |  A9 J
# D& C& x2 b) }9 g! w( d3 u5 B, G
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test9 F2 P; \! M; v$ U" l! }+ w
$tt:   -a -c -b ''\''test'\''' --
+ n0 [( @- A& l" [, t$0:   ./getopt.sh1 o& n0 Z+ L6 K/ ?
$1:   -a
& J; Q9 k2 E* q( R/ p( ~3 ~$2:   -c
& @/ }/ d1 d: E  B) T' o" I$ |$3:   -b; I* V( f7 D0 x9 z' `7 K9 t1 x* L
$4:   'test'  F8 v0 k' y* C! E0 B/ n7 G5 j
$5:   --" j4 E+ A* C& P* H, {" t6 P" R
$6:   . j8 ^8 ?' c: s& w& S
************4 v6 u8 [% X6 V! h# I$ v3 D
Fount the -a option  n- P- g. ?/ H4 l1 M/ Q% `
Found the -c option
% t. q  s$ I$ n% u. K+ y5 YFound the -b option. with parameter value 'test'0 o# U# ~7 \$ W* m; Z# R9 W7 k
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法2 \( v# s2 a! ?* U
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
5 u- U$ y$ }% m4 J. v代码:/ u( Z0 ~( w( ?; Z8 z
while getopts :ab:cd opt& J/ S" e% {+ I+ c4 u
do% @" ~& J* {8 M% M' a; c7 @  R
   case "$opt" in$ i: k! L; H  M2 u: U+ Q
  a) echo "Found the -a option";;& f! P# K6 e6 s3 N- O) Z; }
  b) echo "Found the -b option. with value $OPTARG";;
) D$ \7 c: `- Y- Y  c) echo "Found the -c option.";;' t* s. n1 |) x# I. d
  d) echo "Found the -d option.";;
! b8 r) e/ i2 ~  o9 ?1 s  *) echo "Unkown option: $opt";;- z" i, P2 w. L) M$ P; m
  esac9 e* A6 Z1 z. S: U- S/ A3 ]
done
$ X0 W/ \: s! V: q8 n) g, @# x8 xshift $[$OPTIND -1]/ ~! t. l; W! W& }' Z. ^/ H9 \

/ @: `$ j9 X- q  T8 h$ o$ U" tcount=12 n$ u# u" S9 V, o- I8 ^
for param in "$@"
* _4 v/ @: k. X7 Zdo/ Q/ i  e: e( D
   echo "Parameter $count: $param"& u  w7 v" F5 ], K, x7 u  \' D
  count=$[$count+1]: F* C8 M0 ?& {' v' F; O8 y: r
done
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。
" v* N" L7 R6 t% ]" u3 V9 ]: {其后就可以这样用* W6 ^% q( f: y$ ^
./getopts.sh -a -b test1 -d test2 test3 test4
8 f) z8 q6 S& M' Z  F./getopts.sh -acd -b test+ m, E( d' ]! _' N* h
./getopts.sh -a -b test -c -d test1 test2 test3 8 q+ t0 q5 L2 n; ]9 ~5 w" B
等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash
4 O5 ?5 p6 d( l: L4 s* K# w. |+ I. W% o+ w$ o# ?7 h; D
: Q* o- S) T6 z4 ~9 o1 X0 U
while getopts :ab:cd opt
; ^. `9 t" U; ddo$ H% r7 [  Y* U3 Z! c' P3 [/ G9 O. s
  case "$opt" in
6 g5 }& S+ N# |  a)echo "Found the -a option";;- [# i  m  m) K3 {- [
  b)echo "Found the -b option. with value $OPTARG";;
- N8 P" g* i: T0 |8 p  c)echo "Found the -c option";;2 {: Y/ C) z, u# _) \
  d)echo "Found the -d option";;
5 w$ B* a$ T. n+ \" K  *)echo "Unkow option: $opt";;' S# ~4 Q+ D0 [
  esac
0 [8 U- X; d1 {; c3 {/ |done; [: I) \* N, x
& F0 Z6 ^. i8 p) m# A+ e/ l
echo "**************"
- E, ~) E& o: J3 ]- V echo "OPTIND: $OPTIND"# Q1 O* _5 j" U& X0 N: R
echo "\$@ $@"
- m' _1 q% X8 A shift $[$OPTIND - 1]
1 w5 ~* W5 P$ |' `# ]- U echo \$@: $@
3 k6 f/ m3 l5 Z6 i; S5 D echo "**************"- V/ W9 }1 A  s" J
" L8 v, i+ F9 r+ q  w
count=1/ V4 I+ H  c/ _: J
for param  in "$@"
. M/ F: |# q2 q% xdo
' v. l$ c. ^' Z6 z7 j. l  d  echo "Parameter $count: $param"' E/ m" D9 e% l3 _
  count=$[$count+1]. Z- q4 U, I6 f. R
done 1 p* ^! F3 O$ ~
& ?% L5 \: O1 O; f/ M$ U

3 k8 W/ B* D6 U; g; v; e5 V$ v0 V  f: I3 P4 W5 z' i/ g/ a7 C
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
; p8 Y# Y2 f; F% o7 V% Z) d0 j  W# }5 l9 `( K) X* B4 I9 v
回复

使用道具 举报

本版积分规则

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

GMT+8, 2025-8-20 09:16 , Processed in 0.038777 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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