一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4415|回复: 9

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

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

7 B, p6 l# b+ }% y! sgetopt/getopts:Bash中命令行选项/参数处理
& G9 o4 a& O+ F6 ]% m/ t: `. d( r4 U" V
0.引言
% F+ y; W, h( W/ R: W0 m. O. c2 k( p' X5 k3 _
写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
- Y2 o& W+ e1 m3 M
! i5 z! u5 x2 i" g* O$ R选项与参数:6 B% h; |6 {( g

- B. ~: s) D7 \, B" |如下一个命令行:2 S' t9 Q& ~7 c3 S) T% ~+ i  J

' ^( M% y+ {& W# A[vb]! v' t& k2 f1 M* ]6 I; c
./test.sh -f config.conf -v --prefix=/home
# I7 O+ ^  E9 |. R! R: d! x6 ~* X: ^( y
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
- t- L0 _3 N2 H8 Q- C! g3 K9 {
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。! {! }  x: @  Z6 j& c, u+ Q% H3 A

! ?) ~- y% {' {3 Y* V在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。* d: n( p( ]! m0 X8 x4 R

) ?3 D6 @# M  @7 ^$ b2 g. h手工处理方式
& W. u  F  N9 f% s0 S6 K% w: ~2 t# b
getopts
; S0 |- ?) R& k3 b1 r: @$ J- [. R+ u% a( {/ r! L
getopt
3 ^! z# b" v) O1 y; @2 M4 R
% b" Y) g; p! `* Z6 i下面我们依次讨论这三种处理方式。3 y4 h& |0 y# s( O+ X) U2 I1 l0 W

: L. K- ~! I7 b- h" x1. 手工处理方式3 N  q4 j9 g. S# i5 f- Y
8 n" M9 d1 F! P
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:- U) v3 r; r+ P( {% b/ q! i: J$ l

8 A+ c. p! q5 q2 D8 k" C$ {$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
. e) r5 I$ i) g5 {$1 : -f,第一个参数.3 c) C2 U- X. J. F

: z* _9 T# b  d/ z8 A! y9 k2 R% k$2 : config.conf
* Q  {' s6 e. d, \' p2 o5 O/ x8 L2 Q
# x: u, L- j$ h5 q+ h$3, $4 ... :类推。
6 I2 j& ]9 t* D5 D, W
( t8 S  ^5 O/ p& ^- i3 h" P$ |6 j$# 参数的个数,不包括命令本身,上例中$#为4.* U5 I; V$ \" v0 Q5 J/ _8 Q+ V
; o$ a: _( s/ f* H+ l# Y( K6 b
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home# `# H2 A3 Q5 Q$ v

+ `. q, N& S5 I# h$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:
0 ~7 \. Q5 L, c3 I" U$ @( E6 ]" Z% w+ x+ Y2 B1 {* {4 u2 m/ `- Z
[vb]
/ Z/ e1 a: Y7 i#!/bin/bash2 M: M: N' V; k$ E. E; B3 M0 G

" |: T* `5 A/ C- C- tfor arg in "$*"
! l4 @9 A3 f. c2 f3 `  q  r, M6 Y- m) |; {, @- D- a
do) U* d" k( E4 W% h6 f
0 @( B* Z9 C$ `) P" J
echo $arg5 }. m! S+ \$ J) Q) p2 c
8 T3 d. S9 n' K4 i
done
. N, M. @3 S' z" p  t
1 w% Q& c* {8 ]/ F+ A% k! r; S4 Tfor arg in "$@"
' Z8 _5 [% _$ B5 u
7 H9 t5 s% ^! l% W8 E6 x/ qdo
- e# A3 o1 g, |6 V1 |3 W/ n
$ R# w/ g2 w! F3 @( ]echo $arg
  d) l# W6 Y$ O, l& S8 n
1 e& y( Q- A* Qdone
! k8 M0 \% S; m+ A) L. ?
4 z. y7 U/ ]7 t2 m+ B- u执行./test.sh -f config.conf -n 10 会打印:
9 G) V, t( t3 r. E; M2 |/ H
0 K5 T6 }2 R' y0 ]! d: W-f config.conf -n 10 #这是"$*"的输出
2 P( X$ T- r- `7 d/ H) r! U* ?# y' a! x% l5 Y  z$ ~2 j7 f
#以下为$@的输出
% N  r# ~, e9 ?* O! D
" C- J. c4 P, a% A-f
3 N8 G1 \8 S/ b& ^; S% l3 @) ^. ^8 y2 a4 L. q
config.conf% |5 o0 f) e4 [' f. O! v' `) ]7 H* B

' I3 Y! W1 d) R3 f3 y9 C* J-n6 X. O8 U6 z! w9 X' v
# g6 X8 o+ E" K; |2 L
10
; r- N3 N3 z" U' F' y' s) O% f; W9 ?% p
* b; p# [* ^3 M% e% q所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如' W9 V$ l" a2 ~+ i& J, r5 W
1 l9 e2 u% D9 r! d
“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:( R, T8 T+ ~8 m, r2 b+ e: P" W
2 `2 G) T/ A( t8 }
[vb]  J, p. \( v$ Q& M5 U$ I+ ?- G
#!/bin/bash
4 a  _( N9 b) F. a( c# C! Z1 j+ r4 y1 L! t! C
#if [ -n "$1" ],参数不为空
. e1 i( @5 ^  S. uif [ "$1" != "" ]
# ]8 L5 o7 q/ Sthen8 R, Q- q7 E$ x9 \0 T0 x5 Q; t1 Q
* F2 [8 Y0 g# H! z4 T  o
#...有参数
& n  h: L. q0 `( g# i3 Q& G; D! T" L
else
2 U- m; Q9 a' \/ p8 j$ D' f6 {
# ?+ I6 H  q' mthen; ~; K- K" x2 I5 J! @
) ?* t/ c& [! {, a- f3 y8 Q& A
#...没有参数% a) z6 `# I7 T

% A2 q6 g* B8 p* kfi: P. B+ Q1 {$ K" {7 j- I* i9 s# P$ c

" J( I7 ~: [. u& E& w6 S* O手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
( c- W5 Y' }- O" x( n7 N2 k+ `. A; A6 H6 C6 b  ^* d( [7 s+ V
2. getopts/getopt
% ~/ H; T' C# U' h  D; T1 ?/ F# G1 R0 Z4 x, P
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:5 C) t4 k8 z) C9 ~1 N
% ?, _6 t7 f) c% C
./test.sh -a -b -c : 短选项,各选项不需参数
0 T# z, J1 x) c: \" F
. Z( x; x) l& h- K, s./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
8 T  O/ o0 @4 [5 n) u3 ~! @4 v' g7 ~. d: ]/ l
./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
8 x1 V! L& C% I: ^, O: s  }. P- w9 E# d; M( {" l
./test.sh --a-long=args --b-long :长选项
7 \# [. q) e% R0 }' V3 I4 e$ {' S: x* F+ s8 s- e: c) F8 B
我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh  n4 F' \" ~9 ]4 i( T% I
0 |% _. F: H) k& f
[vb]
. b+ B: E5 q, c4 m# W#!/bin/bash/ v4 N( K( {2 o! Q9 B
2 L6 Z' H" h' ?  T( F& D
#选项后面的冒号表示该选项需要参数& p* J/ ]6 k3 C! Z" X7 Z& m0 }
) [! q! W6 G. C) u( S
while getopts "a:bc" arg
2 O3 L' |* s) g& {" T6 b6 |/ x' X7 M$ s  T
do; E# {' w, p5 `" q- q- s, E1 M
+ S; Y1 c% n# D8 f
case $arg in
  G: d" y7 Z6 h: ~  u
: d, B8 c0 U* y2 {2 Ja)3 @6 o/ ^5 E9 |- V1 s  _- e
" E1 J& W$ Q  n' L) ^
#参数存在$OPTARG中, `1 S& p1 c7 s- s/ z7 M

. T+ f( M5 S: Q3 E' [echo "a's arg:$OPTARG" ;;
$ U- S* x( _9 r8 a) m- d6 U* U( m4 T; G  Y: e: s3 T' v' k# w
b)
3 Z) N# r- [9 G" W( f# {. r+ @% C! s: B0 t7 r
echo "b" ;;: s2 }5 S* d% \& |* v6 [

. E% C: B3 O* X$ F1 `c)
  _) E7 _- a7 O5 r- X  B8 W+ O) c5 g' }, Q" r5 y! r- \' L
echo "c" ;;. ^5 ]; f3 ?; M. A5 I

* ^& t3 U9 d0 v* u% c?)
2 K4 J$ u# L* n. E9 J  z4 c" `7 k/ T1 [" i
#当有不认识的选项的时候arg为?
# y4 t! p" u# Y, U2 ^) }, e
3 @# v6 I& G: K' \5 W& V9 decho "unkonw argument" exit 1 ;;
6 J- k4 W' p6 E; Y( t7 X- W/ Y6 S& A  Z' i. X
esac/ z7 z+ h) j# Y# g: G$ G! T

' K% y% E4 i# o1 \6 m  Y0 odone
- O2 V6 m0 A' b& f. e2 M7 m" Y! Z, |1 D2 n
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
, L; f7 s! O4 A1 m2 V& S) g- [) c
; Q/ K; F# o! A2 G! A* v. Y) o来加载了。1 f+ b0 A! u7 ~( w! N: F

( f' {) j) k3 W' G' ]应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
1 Z3 R/ U3 |+ \) b' B! @$ @6 _% C& G/ i, j: x! ?
[vb]( p9 T8 z% N& d) h6 p9 [
#!/bin/bash
4 O- t4 Q% V5 p
8 G# f1 N0 {5 x  m& e9 r3 G# A small example program for using the new getopt(1) program.0 c; v+ |+ V1 `: |
0 i8 o2 ?7 v2 ~  x" R; q
# This program will only work with bash(1)
( ~  I/ ]' T+ @" q
" @  ^' W5 `" b1 K; d# K! O# An similar program using the tcsh(1) script language can be found, n& U  O$ l* g  u% a: q4 x

" z  g$ z" Y7 c* e# as parse.tcsh
) |9 L) R$ N2 |2 e0 H( B) o6 g- J. p  z1 d4 u* H  p" L0 Z1 R
# Example input and output (from the bash prompt):" e: V3 w, D1 B# k+ S% U% n
1 ~: q' p* g  [/ l
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long ", P) m6 I3 D( g8 r

% @7 D/ P! Z$ ~# Option a
, X6 O- s6 Y( A( ^  T2 j# Y( m: h6 r6 T% e- E$ o  {7 o
# Option c, no argument- b/ q4 h+ z  [& O  M
( ~- Q8 b* V1 U6 x1 e1 B7 l
# Option c, argument `more'! R2 t7 U% |/ \, |- _4 X1 j  ?6 c
: y# f# W9 V' ~$ ?/ |, P
# Option b, argument ` very long '- m6 [! x* n9 N) b1 I) G
" h4 p. B0 S% c3 N
# Remaining arguments:
" p9 K2 y# n# n9 ~2 X+ q: S* ~8 R# U( {3 B( m) }# p6 ~
# --> `par1'
" J  W( i: P2 l% Y& N" o( R+ X; Z8 V5 v5 z. d2 r
# --> `another arg'
) F* D5 ?0 Q2 M6 g0 d; o" M: J. }: k0 t- F$ p
# --> `wow!*\?'$ r8 \: ^2 N8 N6 @9 T& g

( ?6 O0 m: W0 n3 a7 Y) W# Note that we use `"$@"' to let each command-line parameter expand to a
; D, r7 C: M2 P6 j2 h1 }- g) I( V1 }4 ]4 u) J  l4 X7 m
# separate word. The quotes around `$@' are essential!
# ?) K' A" ^4 T0 E
& i/ z6 m- I$ M( G# We need TEMP as the `eval set --' would nuke the return value of getopt.
" Q7 D( U1 R+ h: d2 {+ d" k1 v$ T5 g* |! S
#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项. A9 C$ r- Z& l: N" N# i6 F

8 w; X0 _# N$ D0 J) c- W#如-carg 而不能是-c arg
; K. e/ Y/ H7 l
1 R/ ?+ T* g& o2 y#--long表示长选项
, d/ G- a# p' v9 g# I; R# J) C
3 i" j9 Q# j- I. {, ?! M# s#"$@"在上面解释过
" U: b3 `) Y/ y, B4 r! I
7 v8 @2 A0 f9 _8 {( g# -n:出错时的信息  o, D: z; r& b: a' r) V
: T* {  x* N) m7 {5 I
# -- :举一个例子比较好理解:; I/ E; T7 s) V1 ~. M  d+ Z5 A
. {6 }3 i# }6 d$ I: w
#我们要创建一个名字为 "-f"的目录你会怎么办?+ p. w& z/ `5 S6 n2 P$ [
' i6 t# k  h- \$ L" H- t1 j3 q/ d
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用& `1 D' |2 r4 [( h# O* b  m/ b4 H  S

! z. p$ r# ^% U  q* J% Y" C: p' Y# mkdir -- -f 这样-f就不会被作为选项。4 Y- A4 e) s/ F# ]/ }
6 S, s: {8 V9 O8 e; t
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \; Z* J) h: i" I4 M

! Q1 G6 ^( }: ~- R-n 'example.bash' -- "$@"`
* y& o, q6 y, u- v' `# v( _" |  M2 T/ M' S
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
2 |  z  y1 J, a# Note the quotes around `$TEMP': they are essential!* Q, v% V  ]( o. |9 H

. O7 o! I# m: w- ^#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了+ G( s# Z7 ^! j; o+ E0 ]
$ M) P7 f9 E% H5 p
eval set -- "$TEMP"8 t4 A, |; y3 ~0 E/ m) O

( {* Q0 p) e: b#经过getopt的处理,下面处理具体选项。
0 u8 F6 A# Q2 f& X; P0 x% B
4 c/ v+ u6 y0 Q6 L* ~while true ; do
2 N2 ]) i8 c0 e, r9 Z; o
' L4 p# F% d# q3 X% Lcase "$1" in; \" ]1 J. H6 m! g, m- k7 k+ v+ n

2 O1 ^& t) R' E1 K  e-a|--a-long) echo "Option a" ; shift ;;
7 ?. G& q" ]! K& x6 |. X
; _6 z- m) N2 `$ j3 A-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;% d6 f# S5 t# R% n1 W8 r6 N& T
$ a# r1 P  K0 E0 D% T4 S
-c|--c-long)2 G( o8 J2 r8 Q/ P8 P! x
  C0 x3 d6 O  l+ K
# c has an optional argument. As we are in quoted mode,/ e7 `8 M+ R7 {: {2 u1 y; n$ B9 y& O

& O+ @$ c+ p" p# an empty parameter will be generated if its optional2 C% T3 ~% U$ V# d

( L7 W: X* }2 |) S# argument is not found.
+ P( p* _5 Z( j. t$ c' t0 v. n4 K1 k& W/ b' d9 q
case "$2" in" i& \) f% z0 w- A  |2 I5 x, E
8 B" h+ M7 d, t0 j9 _2 ^9 k' P
"") echo "Option c, no argument"; shift 2 ;;& r0 B, z2 u- C- {/ C7 C
$ M! j8 y) b8 W" `8 u: t: Y9 \9 i
*) echo "Option c, argument \`$2'" ; shift 2 ;;# d/ j; ~% G! q8 h$ H3 K  e8 E0 x

0 A5 c. w: K# d. G" a* ^esac ;;- J% H5 x+ ]  ]5 N
2 a& t/ \* Z: f( Q+ D
--) shift ; break ;;/ f9 M0 B7 p3 d4 Z
$ Y! l0 u. c/ z% Z
*) echo "Internal error!" ; exit 1 ;;
* m$ p. U- F9 t7 W$ |8 H9 j5 F: }4 Y- \  ~, [
esac
9 ~! _8 Q5 Q! W& d" |6 f' S/ r
) F9 v& T% R0 Ddone
# T& u0 X$ v' I
' c7 X5 ~3 h1 r: Necho "Remaining arguments:"4 Q) T* O: C. m" e: P

2 |* i8 ~7 D# b. Tfor arg do* L0 [, M& L: ?+ ?

6 g0 M( B  y- @  s0 xecho '--> '"\`$arg'" ;
3 l+ q$ b& S. A# b/ y; u! P" a
1 a/ h! @  x6 @% L9 f! t& kdone
% q# t6 T7 \) V. p$ ]$ [' Y, }+ p: Q) I( Q2 n0 T" Q. @
! v6 F3 ]' r9 T2 e  N# x5 V
比如我们使用
( [: C; \/ B1 s1 {" E* }4 ^4 [1 W# S/ |0 f2 o  d" X
./test -a -b arg arg1 -c
7 S0 L0 R+ j, k1 Q& W! S
" M) z0 O0 b, h; J$ X6 D你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
; h1 |! k: d1 h, W. U* s: F* I  t. J+ n0 ]; h9 H- V+ e9 r
-a -b arg -c -- arg1
! X* ]% m6 M$ Z2 Y  {5 M- x0 k' B5 r( E
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。( a; }# S2 C* p
% a3 a( J' V+ T% Z$ @
3. 总结8 g7 Z/ A: `6 b' t
4 v. ^  \) k: R2 t, z. D' q
豹尾。2 s: r: h7 W! T* Y
  q& c4 ^( S8 c0 C6 \$ [; n
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统7 ~7 @( H' ~7 F8 f6 r
2 b4 G0 T5 Z$ C. U
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:335 B/ q, @! A6 R3 ?- I. q' s& T: j% B
记得getopt常与shift结合使用,while循环一下就好了。
& u' n( {+ ^0 F8 O" r" a
请教一个问题
8 i% d3 e) U- @( k5 p! b5 U0 E有一句 :set -- `getopt -q ab:c "$@"`
( n) u" l- s( q" }: I4 Y) k请问 这个如何解呢??
9 n+ `( T7 j# M' b. {7 X1 p
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句: M) B$ R0 T- f: ]6 D  S
set -- `getopt -q ab:c "$@"`4 r5 n8 L+ J5 M+ V3 N6 j* S( I
while [ -n "$1" ]
2 j& b- S$ H( j( @0 V0 H& Ddo/ n1 @  x7 r6 m4 `5 y4 e2 x3 H/ e- ?
  case "$1" in7 {: V6 V, X$ q
  -a) echo "Fount the -a option";;% F- z9 D3 g, z$ ]# U$ c' M3 O
  D4 n$ {* c, k! `
  -b) param="$2", F# u$ E9 {+ n! P% v' q
      echo "Found the -b option. with parameter value $param"
. L1 q# C1 N& `( t1 y. v5 Q  l      shift ;;/ z0 p8 B4 |* ^/ y
, u& H4 m0 y( f2 N# l6 L
  -c) echo "Found the -c option";;
  ]" {8 G" P' [$ j
- s9 J5 v' r6 R4 u# @" U' L( U( |" ^  --) shift" X+ x! u# C$ |+ e! [0 f8 Y
      break;;
5 @% _* w. x% j- Z
( t- b& m! r: t: N; C( \( D- J  *) echo "$1 is not an option";;
0 g8 G, J0 A" f9 c) c% E( S5 D  esac( d8 w  t- A. n, m
  shift
$ |- x( v1 p3 Y6 e+ _7 R  done6 H" R: e* S, J+ u$ ^
1 e2 x4 ]& c) C+ H1 X$ [- ]
  count=1  X/ c* g( g' R( t
  for param in "$@"
, U4 O% h( V7 x) }1 U) O  do
; e' n& r0 J/ I2 @    echo "Parameter #$count: $param"" v  q) L) u# |# Q; @5 J$ ~
    count=$[$count+1]
$ I7 R4 T8 W  u" `5 c% X: c" n5 V  done0 M% X1 V& a# x& i  o
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39' V+ Q1 J7 T) r
请教一个问题
/ W5 l' G# P7 ]+ O% ]7 v有一句 :set -- `getopt -q ab:c "$@"`" A; `# y- S" ?) ]7 o
请问 这个如何解呢??
! T- @2 @% u2 B
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了9 o/ t# i8 x0 J
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
. r! c4 z- ]( F( w+ o5 |请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
! y9 z& @$ k  S' F- c! T/ t' c
呵呵没关系,大家一起学习呗。
5 D5 w" ?; g8 M5 @0 N; A& N经过一晚的思考,我发现了之前我看到的一个语句:set -- -F* M! x, f7 I  w0 ?- U
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,
* L; l$ r! f8 C6 O0 C/ @所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。/ S* y/ y2 B3 t0 L+ t
如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--+ w0 Q  V/ t; C6 v' y2 ^" e% S2 c
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
; w% R8 }) E+ Y; s$ `3 l% v5 p/ x- q补上昨天调试的代码
, R+ u0 X+ r5 ^
* j3 G' ]  P+ D+ T& L#!/bin/bash
$ D" @" s+ E* c# B$ Z. Oset --  `getopt -q ab:c "$@"`
! Z2 U6 s  S: W! }$ L4 @tt=`getopt -q ab:c "$@"`
  E* a) }4 K, y/ kecho "\$tt:  $tt"
! k7 [" P& O0 ?! k6 r  X  h( Q% Y0 Zecho "\$0:   $0"# c  e; P% g3 h& s1 `
echo "\$1:   $1"/ r* I1 t2 a. I8 @! t
echo "\$2:   $2"
: h- n4 H  P: d9 X/ j. A- L4 _! O/ _echo "\$3:   $3"2 v& U& m" ]% e
echo "\$4:   $4"
! @: ^/ u" `4 zecho "\$5:   $5": e9 G0 d7 g' K2 O
echo "\$6:   $6"! z% ]+ T" c' E; Y
echo "************"
* k. n6 _' K4 d  V& R, Y& Z- S4 `
. j+ E+ z( Y; H! Z, l- K- L* b9 |( b! w4 `; p/ h
% O# {) ^; \# |8 w. l
while [ -n "$1" ]5 |: t9 ^+ _" x2 b- M
do, n; {# @1 ^3 v! ?
  case "$1" in5 T/ h& m8 ]3 f+ P  n' A9 U* w; ^5 R2 _
  -a) echo "Fount the -a option";;
# |2 F5 c# g9 J9 K6 C& G) O# g: x" s' ]0 @1 |
  -b) param="$2"7 ^8 q! k! \# q7 D
      echo "Found the -b option. with parameter value $param"* A% F2 v/ }3 w: P2 }  Q9 p; U
      shift ;;
' L. N* p, h9 N' N8 L' l: [( l+ m# C' s! \; V
  -c) echo "Found the -c option";;
  v1 F2 X3 w, \1 t$ G: M# m0 M* Q2 l. n
  --) shift
! ~5 z; S; F' V$ o& a      break;;
# Z1 A# y4 h( I; H) q( y+ T+ O" p4 X4 y% r5 K) V
  *) echo "$1 is not an option";;
; Z$ z( s2 C+ M  esac
$ C+ u- ^. ^7 Q: ?3 E" p  shift
2 N7 O. P* |+ p  Z1 {, U5 n* u, r  done* E% C' k6 K7 {' {9 h3 D

  y' ~# p" h6 `+ M  count=1
7 X5 M# L0 U, t6 N* s  for param in "$@"
9 C' ]- {( k5 R  do& F; C7 A. N' Q. H8 ^) o
    echo "Parameter #$count: $param"
% }9 X- R' ~8 u9 b    count=$[$count+1]
' D1 Q+ s' S; z7 z/ v- |  done( Z) G8 D" z0 V  c, B
! `% t& U* X" s) E( c

; B- U' a3 B3 h& a2 R6 C5 O/ z. N7 A( ]8 i# d1 |
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test% T; O( ~# c% H  d, C' i! n
$tt:   -a -c -b ''\''test'\''' --  S* A5 w8 J% x2 H9 o/ ~3 w
$0:   ./getopt.sh  Y% j, E) O+ [- g3 ]' A8 \% c
$1:   -a" @8 a: c7 o! d. l2 }! q
$2:   -c
2 C. D, ?4 B+ j! u1 [5 T: W6 R$3:   -b' e1 i, c) K% }
$4:   'test'& M, j- E" w, n8 _! z
$5:   --
: d0 \, Q7 u; U' e* l' W$6:   ! E5 s* l# q3 F: o
************9 q; K6 e; h  r
Fount the -a option' P/ J. d. u3 b, V! g, e% W* d, n; ]
Found the -c option* m- F; c' ^- ]8 g
Found the -b option. with parameter value 'test'
9 O  |3 \9 d. K7 e7 c
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法
( Q6 ^5 T: @# u: i. g& \getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
+ ?& i4 G4 n  S/ O代码:
9 J% E& B( v1 R- H2 i& }0 J) gwhile getopts :ab:cd opt
7 V& `& R/ N  m, Y. S* {6 [do, B# I' V/ W& n3 y4 R" u4 A6 ~
   case "$opt" in
! T: p0 U  m3 C  a) echo "Found the -a option";;
& t  O: o* `6 C, `* b* {7 v) I  b) echo "Found the -b option. with value $OPTARG";;# o, x& c9 X4 d) D) y+ Z$ f
  c) echo "Found the -c option.";;# Z% i- W* G( ^1 m
  d) echo "Found the -d option.";;0 D6 A, R2 Z- D' K) F0 \7 v
  *) echo "Unkown option: $opt";;
3 R( Z% y6 S3 k2 R  esac
/ G% l8 V, b  {" [; Kdone
9 N4 X3 K# B% x) A* @7 Zshift $[$OPTIND -1]2 ^  D. I- C! F2 k" e
7 n, I" F" \7 f" v+ @
count=1; @. }8 n( q, i9 u
for param in "$@"
) N, `  g& z7 ]3 p; `; Edo
# r% I  C2 W( d$ r+ S7 J: h   echo "Parameter $count: $param"
# E$ c" C' l, `2 h- S' a  count=$[$count+1]* K1 j) P: t0 ?! ^0 s* |
done
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。* z+ n$ I; f2 k; }$ v8 ^; V
其后就可以这样用
; Y% i" D0 J# k./getopts.sh -a -b test1 -d test2 test3 test4
8 |: i  V6 U! {/ M! T5 V./getopts.sh -acd -b test
+ ^) I6 U+ d8 @) D4 r; A. M./getopts.sh -a -b test -c -d test1 test2 test3
5 A; s8 b! ?- h+ u9 G: Z等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash, ]# ?8 D( V5 H5 n4 C2 k- A
$ V; k4 J! B0 z1 t% O1 A

+ x- ~  V# \6 |6 _( ~* Uwhile getopts :ab:cd opt
; f4 E" S/ d9 Fdo
2 Q; K4 \+ V9 ]3 F5 M; J; o  case "$opt" in
% T3 c. Z# Z( l( @) {9 X  a)echo "Found the -a option";;+ l( i3 {# A2 W$ U! [+ `
  b)echo "Found the -b option. with value $OPTARG";;
3 f3 Y* W' d, X9 Q! F8 m! l9 U  c)echo "Found the -c option";;
  Q' w/ f1 u. }, q* z3 n  d)echo "Found the -d option";;1 Q1 Z+ r! c4 L- C
  *)echo "Unkow option: $opt";;
: I  j3 X( `) l9 I9 x  esac
' [/ B, T9 @8 W! m& v2 w* I1 v- f$ ddone0 ]8 W* f" i& v' `/ t1 l, E
$ ^4 ], D, A5 ^! q# ~
echo "**************"+ M8 N5 l$ l6 q7 M) }1 @4 b/ v
echo "OPTIND: $OPTIND"
2 u2 W  M8 ^1 _# P echo "\$@ $@"/ z" l8 i" ^- c
shift $[$OPTIND - 1]0 g" @8 M/ r. _
echo \$@: $@
2 O$ m# G' E1 g1 h. { echo "**************"
0 m- n" K) Z7 U- R+ Y$ g  }
5 G! [% ~2 r# M4 z+ x3 }count=1
$ W. N9 A' o5 q% Wfor param  in "$@"% r; v& U3 v' b. y. S5 D9 p
do
' p3 s8 c% o$ n7 C0 J: t7 D  echo "Parameter $count: $param"
2 L* o' M2 p4 }1 J! G  count=$[$count+1]4 N8 m# r( H+ f2 C" ~* C/ A
done % u) ~+ w: U9 N, @
& o; T- s; R2 X3 c# l

. h' U9 z# h" W4 K$ v! z4 o
) t" o2 z8 A. E; {其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
; x* w! u- Y% K& o1 m( P6 L' u6 K5 C* [$ w! z# s/ j
回复

使用道具 举报

本版积分规则

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

GMT+8, 2025-10-28 23:25 , Processed in 0.038214 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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