一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 5048|回复: 9

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

[复制链接]
发表于 2017-2-21 23:15 | 显示全部楼层 |阅读模式
. V6 ]6 E, _7 |8 N! ~
getopt/getopts:Bash中命令行选项/参数处理" b4 m% ~. v3 l
$ v& I, t% D3 \5 E
0.引言
6 Q' T" N5 q0 E
0 G7 E# C$ t  ?. c+ V写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。: T7 e* |* h. O) K
  h! a: D# Z) V& J8 ^& w
选项与参数:  A( s9 |7 I# X$ A# L

% Y0 L8 z2 e6 o  _' |) O. _5 E) s如下一个命令行:, \1 h* _' T) a( p
' T, V: j3 d2 P4 F8 B
[vb], Q& l* L& m$ i' b
./test.sh -f config.conf -v --prefix=/home9 o& z7 I" T8 w  u. q" D7 F
: O# D6 X0 U4 A; M3 p) k1 J# u0 ^& ~
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
4 }# k; o. ~9 \! z- \& Y
+ D4 V+ l$ ?4 h2 [--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
, h) u  R$ J6 r# }7 o/ Q. V, J! d
8 ~3 }7 a& ~% y& B; @% s( r' d; J在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。7 A. |$ \* S) Z, W& D3 N" B. ^  ^
6 u" x2 ?3 r7 w1 e) \) Q( _
手工处理方式+ n; \( c3 c1 x9 S( Y  o
1 Z. W9 {0 O# C5 _) \7 N9 f& l+ P
getopts
6 u* m* O( M4 j( X3 f/ b1 r6 S  f% I5 p5 O" U
getopt
1 U0 P7 j1 R: S. Z: ^% P) A2 \5 s/ ]- z5 }  I
下面我们依次讨论这三种处理方式。
3 h& h9 K1 o# [& ^: l0 S9 P+ V3 z* B, w
1. 手工处理方式
' a0 z6 ^& q" \1 Y- r8 A: B% c5 |8 W6 u! I8 g% D" s3 c
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:! M% x! z6 `; }* j4 P
% W: K8 l/ @- _3 h8 w
$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]; O" m% |! A" ~# z. \
$1 : -f,第一个参数.8 ?5 F4 I: W6 i) A  M# H
" M. O) w( {& o; o$ W! w- }- c# n, X
$2 : config.conf) |5 K: u1 ]3 `- d, }2 C4 f

7 I6 L6 M0 n& G. l0 ?+ ~$3, $4 ... :类推。
* L3 J0 K0 i4 F$ x2 j
+ j# L4 H- s5 H. H- X7 E$# 参数的个数,不包括命令本身,上例中$#为4.1 H+ j* w5 }1 G: ?
" B! D9 r/ h$ p- n# _
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home& d# U' \# h( f

2 I1 C; m7 d$ o3 l3 q$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:: a2 n' p, p* r  j
, ^! M: R. t! e4 x+ S
[vb]2 p* D2 a" Z8 f  |
#!/bin/bash
# r8 R! s8 A/ f2 s/ z0 R$ x" b4 F0 M$ E  {- c7 q/ Q
for arg in "$*"
" v! U0 y7 m0 `8 x" }0 B8 J. \; b% H( d( k' g5 T: y8 |" W0 H
do
0 j) h$ R" o8 a1 [" o5 Z
! h& z" [) @8 S" f1 i" Cecho $arg
4 U7 g9 m8 N# P* L; S; A# C3 g1 L% E7 B! F7 c) j( J' u, Z
done. J& x. O. l. V6 d- s
' C4 V+ v- @( g+ {6 m
for arg in "$@"
$ x5 R* M- F3 R
% Y  P. ~9 i: I& e6 K" Tdo2 B0 m* I7 m5 g. d9 @% S

0 a( C6 ?7 ^6 _6 A2 D/ n5 q5 zecho $arg/ L8 R8 G" l' ?+ `+ d
2 J/ a2 q( M5 {* W2 x# {
done% _' |8 u$ y& y# \7 u6 k
; `* S5 a' d9 T  O" s; @& s1 Y6 D7 |3 [
执行./test.sh -f config.conf -n 10 会打印:
  ]5 N! h6 ^4 g3 m' n$ {
6 }. k& k6 J. f: \( Z: L-f config.conf -n 10 #这是"$*"的输出- `  [( t! h+ O0 S4 a1 m

/ X4 U1 {) ]. B- Y9 `+ D# `9 V#以下为$@的输出
. k. V$ \5 l* W9 @  K' P7 B* T4 s
-f7 m7 J. V# A: [. C  b

5 d) F, A+ C1 K" E+ m6 k( E) oconfig.conf
# Z8 e. r+ @* ~( O1 M* @$ b+ y% k; k7 p
-n
4 g& T; [1 D; g# p
2 t! t0 D% T+ m, B3 A/ _10% {. g( L) k  [6 V
! y  o' h2 R0 }
所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
2 k2 g" m" q2 F8 W0 L) @, `
0 D1 Y9 W2 w0 D! k* m5 k“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:+ h& z" r3 c$ n; N5 s
0 `- J! ^7 k+ f" b/ }# R- I4 @$ Y
[vb]
3 Q7 w" p) i1 k8 m- t; d+ a#!/bin/bash
8 N, O' x7 Y' r) z& j6 `4 R/ M3 T8 F+ d8 H# [( ?( _) x
#if [ -n "$1" ],参数不为空 . Z! V5 |* a9 K+ y! U5 ?$ A+ {
if [ "$1" != "" ]
! |0 J- E5 P( a' N8 X6 [then% `% j0 k6 B. N: N. p
  a) G- L  m! h/ _/ E7 H7 v
#...有参数- n* R% A- E- ~  f- @8 t' a" d

* j) h9 m. W7 e8 _0 X% Zelse
1 F! p' Z$ D. a0 p5 R+ D, O4 H/ E9 ~0 u9 S; Q0 r6 Z- U: u
then
1 e  F$ R6 v; F5 [) t. e0 p% ?5 o. _4 f, j* l
#...没有参数
% {/ Z0 `& @9 J% ?
* Y7 S* l! K% R# mfi
* @  b, n, E0 G0 r+ z! [8 x% U8 K
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。1 L$ H9 R) i7 M% k! L
( v0 B) q3 q, f6 K8 z$ F
2. getopts/getopt
2 |/ k( N7 f. O5 V& @# r; j8 g% T& e1 `
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:' ]9 k. k3 P: n
# H# v) t) X- k' F* Y$ N
./test.sh -a -b -c : 短选项,各选项不需参数
! k1 n% n2 r/ I9 Z& `
; D# u5 V) h, p8 E./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。; y: D+ |  s( b9 T: q6 O1 l$ m& |6 V+ z
" q! W& R7 \6 K$ c' q( k" }6 M, ^" t
./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。1 o" j) h( Z. \

0 ?) B; M2 J# h* \) {+ e+ J9 V5 K./test.sh --a-long=args --b-long :长选项
" _  ~0 q( l' k+ M. z( U  R. }: C4 r' Q2 t" j6 _, h1 F# }
我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
* t- v  C6 L* F/ ]! x6 y' N7 Z- b9 w+ K6 O% v2 J+ a# Y6 F
[vb]" m/ Z3 F9 [) ^2 d
#!/bin/bash
7 p3 ~! a8 \, P: K/ o) L; G+ N' Q
! Q+ U- U- E$ Y+ q. X4 F* L#选项后面的冒号表示该选项需要参数
+ W" o8 o. E1 R$ ?+ P
4 Q/ h$ r$ }  G1 h% |0 Lwhile getopts "a:bc" arg
! @* S2 q5 U) a9 W0 Z% W" N& S7 Y! j- m/ G% i5 ~4 P4 E
do# m+ d5 S% q! [. w  `

9 y. `# r- L. w; ncase $arg in7 `( X$ n6 g( w; K
) C. L6 }9 ]  s7 P# y: @
a)
5 J0 I- x0 Z1 z  C  r/ w& }
; f; T1 h' X, d+ Z#参数存在$OPTARG中
# F# F! V+ }, `
. @$ `0 v$ c# @; N" m6 kecho "a's arg:$OPTARG" ;;3 A+ `' l" o2 I  Z- j
  \% e" n+ {# C  J
b)8 r3 C8 e8 ]- h
  _: {# [  X1 F
echo "b" ;;% f. z! d' m3 S$ M
7 ]" O. K. l( m% {7 r2 z
c)" K9 I# i+ A# e- i$ _1 ~
4 @9 A# b, ^' n+ Y
echo "c" ;;% x6 `, F1 r* z6 Y* Z1 r4 `

, N0 @4 I; a3 R& F; M7 X?)9 @  l2 G9 F. b! M6 G- @  J6 i

& M) t5 P; y& A1 E& F0 E& \#当有不认识的选项的时候arg为?8 O$ ]2 Z- C- h' L$ r
! Q' ]! M; S% Q5 X: L/ o3 S
echo "unkonw argument" exit 1 ;;
9 ^' X  n! E3 I9 p% N; r% z) x- r
6 g; U% l) H: W# o: s' f, g: nesac
; R* w( r, S. B$ Y. x, |5 Z# I. Q- i5 H! \- H* @. o, ]/ f7 O3 G
done
, ^% c! B6 x  g6 i9 t+ A$ x- M* W; ^- M- Q# O% G) X' g) h
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
! {, O8 Z3 o. k: z/ ?2 y) `) I$ c6 j7 A6 v0 z
来加载了。2 R( f( r: n+ A
; p* ]; d# f2 i+ p: i
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
+ U8 w  ^& `' O' W$ r7 t. b: H$ }6 f5 j0 D! B
[vb]. L- a8 C4 \& f* T' k
#!/bin/bash
% W9 P( f; j4 H# |) g
4 l# @5 m/ S  s( X: ^4 C9 F# A small example program for using the new getopt(1) program.
) c; F- }' @! ^4 G* z
/ c7 F! s! }1 N$ M# This program will only work with bash(1)& e' e1 r& U6 b8 b! P# c" ^

& |/ m1 Q0 ?  w5 u+ m  ]2 F0 O# An similar program using the tcsh(1) script language can be found6 N/ g8 b# ?$ S0 A
7 U$ b+ t) F& F" i9 j
# as parse.tcsh
$ ]& {$ N- q: q! l$ G
3 R" r" j# R- B0 z7 t; |2 i" L+ L# Example input and output (from the bash prompt):
; m) x" D9 ]% S3 c4 d1 P# M0 L4 b% z: B, V
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
4 p! @: R0 W+ j- J8 q! }: A" t( b$ |3 X9 ~* f* z3 A
# Option a1 m4 _4 L+ Y% h' _) v0 G) Y) l
; W1 Q( t& @9 L6 w) p2 v
# Option c, no argument
7 u2 X0 t8 R  U/ Z2 y9 j5 j7 z8 h& i+ h) R) g; f- q
# Option c, argument `more': S2 @5 V) {' d( v% s: ^4 z
9 Z# p& K0 Y: l9 C; d: ^  p
# Option b, argument ` very long '3 A# F9 i* c$ Z$ j8 h5 ~$ p
7 B: Q$ ^- x% y! X) Q
# Remaining arguments:8 Z' j3 \2 m8 V9 w6 T0 C
/ J" {' E2 _1 b
# --> `par1'
( B5 p, B" {2 y* t8 p# P
2 k5 |; `" B" U7 d( I- ?6 {4 R, W6 K# --> `another arg'2 Z: a, x4 x4 y" m- R
3 E; i6 H. C+ }1 }
# --> `wow!*\?'& j7 p- ?1 o1 f3 U- b

5 E& m1 W7 D! E/ k; t# Note that we use `"$@"' to let each command-line parameter expand to a
+ g& i! u: d5 i; T. C- B& M2 _9 c- ~2 N* z  R) _. ]6 _$ d- L, ]
# separate word. The quotes around `$@' are essential!
1 q" e5 K1 M& t* U" X1 Y3 ?  N" f7 _$ S
# We need TEMP as the `eval set --' would nuke the return value of getopt.
9 v. ?" d& @) h! i7 m8 @
) o9 `& y- i& K9 S. t. m6 }. p#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
! M' j7 q8 i! T
0 F  v! A: n4 Z( M, R#如-carg 而不能是-c arg
/ m+ X$ k  x+ p/ [( |4 g( ]
. ?' e5 B' P% S. R- [& ]9 n8 p#--long表示长选项
4 @' W& Q0 o  v+ Q; h" H0 x/ e' |, R9 j: r% d
#"$@"在上面解释过
! M, `3 y+ w6 h/ S
- [8 b# a/ b/ D' p# -n:出错时的信息5 N' X8 q0 J' {4 T! @
2 W0 @5 J& q1 }1 w! s
# -- :举一个例子比较好理解:) q. ]; }$ u% e2 v

# D/ l6 ^: b. q2 d#我们要创建一个名字为 "-f"的目录你会怎么办?9 b5 b6 P; F+ u* x5 ^4 B7 D
0 g9 F: }, J5 U( v0 g$ N/ M
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
! L) E$ M/ ?6 G9 @( a0 D1 ^
# M- X; ^$ y- M" Y# X# mkdir -- -f 这样-f就不会被作为选项。. I* i/ e* Q  B  o: n8 }( g% G

" P( F( }4 `3 J+ x1 MTEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
- g/ E* V$ t# y. L" a5 a$ e" u
7 N$ D8 w/ t2 D1 W-n 'example.bash' -- "$@"`5 }: Z9 s% \8 C, g
, @  A/ N! ]  b" V0 O9 i; |
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
9 p. m4 G: o: f& f2 A& H# Note the quotes around `$TEMP': they are essential!! u; ~; T+ y, |$ \
1 S! A) O, g8 a( ]2 \; ?5 E% k
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了* Y4 ?8 q$ E0 e$ ?7 F. i
" O7 P0 y+ A9 I. Z: [
eval set -- "$TEMP"- ?0 Y, d6 Z( j
8 h. D- G0 t! P2 Q$ H3 C8 ~
#经过getopt的处理,下面处理具体选项。7 @8 N: J8 A- V5 \1 {; l9 e

/ j# J$ o8 m0 bwhile true ; do1 ]5 b! B, j5 D! q; E, L

9 m, Q/ l/ D8 b" `$ u4 _5 ?case "$1" in
9 F# L8 j( \8 R+ s; g) A2 G$ s! s  r; L7 N7 y
-a|--a-long) echo "Option a" ; shift ;;
9 p; R9 q- ?+ U+ N* H" A% k: X* c& E* P/ v$ \$ p  E6 T9 s
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
0 ~, u3 q. n5 V8 R. |. I, W: v. B4 H/ A* L
-c|--c-long)6 _7 p& |6 c$ R# j. `* V" P) o: A

5 m+ C& g" O; g6 X6 T% m# c has an optional argument. As we are in quoted mode,
/ Y2 ^) b: H6 s- O8 {- T+ I, R0 t5 q) o/ e5 i7 q
# an empty parameter will be generated if its optional! U- `$ _$ i1 A8 }) q" x
: ?/ U7 w2 _8 R1 f* c9 W* ]
# argument is not found.
5 m9 U3 i- L- n( M7 Q
' q0 H/ x7 P* J4 y* W& Tcase "$2" in$ t& O8 D5 B; }4 D
) X& ]2 W8 G+ O$ w$ u
"") echo "Option c, no argument"; shift 2 ;;1 S* t) r* h! V& Q! i

2 N$ u9 t/ ^( p, z, v; F*) echo "Option c, argument \`$2'" ; shift 2 ;;# w, X9 @' N  P  X+ I! V
2 }+ a  a; r5 t3 K
esac ;;1 ~& ~$ ~/ a! I) ^+ A
. I( \2 ~' X. i3 U3 [
--) shift ; break ;;
  @; X+ e* K+ Z6 G
2 \& J7 h# M6 U0 Y+ M*) echo "Internal error!" ; exit 1 ;;
: f. W* Q; }! ~# I1 H3 b( X
& o/ s& ~/ ~6 O8 h# x" Z' Q9 [; vesac
- t2 R  H; Q* A  k/ X% Z: Q, H1 C! l2 v6 C
done" w7 F- ]( f& z- b7 B  m

* k2 y& x9 X' _% W% e! v- [' H+ Gecho "Remaining arguments:"/ C: F7 S, A( G1 `4 a8 _( j9 \
* \# Z$ L  }3 f
for arg do
' C. d" l, M* z1 x) Z8 R+ b: b; N4 |2 V; G9 Y: O" z& T  o, G* g% f% P
echo '--> '"\`$arg'" ;/ l# _2 M) J# z" P
' N- g! p' C) }* k: z
done$ _3 f$ [$ m" Y. o# K
8 k3 H$ `. n4 A' X
9 f/ r% N1 q6 F/ A8 x: K. @- X
比如我们使用2 z3 j8 \! }! U% i
1 z0 p# r4 c" B9 K0 Q7 C- B
./test -a -b arg arg1 -c
+ A2 g. j( b1 X5 O! h! t1 |" m+ Z" Z1 M
你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
( c& H. j; R' `9 a9 V9 x* h4 _. h7 ?& M4 k
-a -b arg -c -- arg1' x! o" e: @) y

1 V# |+ ^, z2 Q6 ~# ^1 C  W% y& L$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
$ g0 L- K7 m( F
, n" S* T- Z! Q: I' f0 d# p- g3. 总结$ W1 f4 [$ F6 {, x

0 w, l1 ]- S# I+ B. V豹尾。. Y/ z8 L& t& x  F1 D: ?
7 A3 K8 D& Z' y" E' v4 U
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
- ]/ L* I1 g+ e+ s' ^: A
# ?" E: u( \) g, q+ n
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
- w( m* F5 q' j记得getopt常与shift结合使用,while循环一下就好了。
/ ]4 m# ^% N0 V* X+ B! @4 V
请教一个问题
" G$ {1 H: z- }% E1 F有一句 :set -- `getopt -q ab:c "$@"`
1 _+ M$ a( Y% ]# a% W6 I, s请问 这个如何解呢??) m' v$ j$ I, v' H$ l6 a
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句- `; v4 v1 p/ R# ?
set -- `getopt -q ab:c "$@"`& c1 h/ z- L8 l8 s
while [ -n "$1" ]
4 H1 k# f0 R, o8 ?5 ~do! N" C9 q: v' V: v# k  o
  case "$1" in  D3 a2 B2 b( h4 c; P4 C' ?2 m
  -a) echo "Fount the -a option";;
* I2 _' |) @5 g4 a, B  f! c: |- d8 d  T8 u
  -b) param="$2") x& e; L$ k# }, U0 m  F9 R, d
      echo "Found the -b option. with parameter value $param"
& V1 C; L! k+ v7 w  O7 |      shift ;;
: ?3 {1 E2 S/ i* m( l5 y! `1 K5 F
7 c/ n- `; E, C5 J  -c) echo "Found the -c option";;
' \9 M( e% a9 B3 O: V1 h
! ^$ E# s' X0 |1 C2 M4 l9 e8 T. z  --) shift
3 E- r1 ^* ^: _; a; U& G      break;;& |0 k, n  L, ]
# W' H" {% L; q, A* X# n" c
  *) echo "$1 is not an option";;
$ F. V( W+ _6 p0 Z. r9 f! [  esac
/ P/ ^: I6 g1 W. I8 R) x2 u  shift8 s0 j  r+ A/ C# a" O( W
  done
+ S4 ?5 r. K( g6 I( q 7 G7 }$ |, B' P" l. V8 W: ?
  count=1
( V3 z2 ?8 e$ A9 o7 [5 @- ^5 B  for param in "$@"7 ?& Q2 H1 K# T9 U5 h3 {
  do
- v) ~7 Q& l3 t6 B. X4 [% f    echo "Parameter #$count: $param"
% `9 p4 e$ @9 W5 H; s- ]# S& p6 x    count=$[$count+1]1 K9 m1 F/ t+ f
  done9 t6 J* D7 w# ]2 g
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39  T2 W( q- A7 K3 O" x
请教一个问题
. p1 Y4 @5 K* h' @有一句 :set -- `getopt -q ab:c "$@"`2 {5 G3 t0 h7 m+ ~7 x
请问 这个如何解呢??

5 Q* G+ U2 D: K# r+ h6 n! c请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
3 A2 p$ [2 q! ?# p
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
! P7 u% z1 ~2 o0 P* p" V. \$ {" _请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了

3 u& {! o* N, Y8 x4 b4 y/ F' i8 K呵呵没关系,大家一起学习呗。9 S/ K1 N" `, A- T  F
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F
7 J$ X, k$ M$ D! }! W  Q+ m一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,- a! r* d5 O5 t$ y3 p8 w. w4 M
所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。  ^; B# b  q+ t
如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--
' t$ x. ?2 K0 K" |, ?$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
1 O' s( c7 I5 a4 F3 Z补上昨天调试的代码2 \/ y8 t; K2 v( K1 Z0 q
, `% y) o( H2 ]8 E- ?/ Y3 i
#!/bin/bash8 a9 V* F$ i/ S# m* {9 o, M! S4 a7 F
set --  `getopt -q ab:c "$@"`
2 I* W5 l! |+ K( M9 d3 S& o  A7 htt=`getopt -q ab:c "$@"`2 X7 ?  J/ u6 E0 v
echo "\$tt:  $tt"
8 t2 D+ D% M1 i* H+ `echo "\$0:   $0"
" {1 ~( R6 M7 P& W/ Recho "\$1:   $1"
0 ^& ^& b, n( `0 r+ Iecho "\$2:   $2"( j) W6 P6 x1 p3 O% P  G$ T3 u( t9 [3 [
echo "\$3:   $3": [. i) i+ r* I9 N) E
echo "\$4:   $4"
* V: b! i' ?2 M" N8 c4 m! V7 E6 wecho "\$5:   $5"
) m8 ^$ {1 |. k+ |) V5 o$ aecho "\$6:   $6"
8 m) m" V  ~3 y, w6 D7 t5 Secho "************"9 g& K- I" y2 U+ Q& k
! k- O) B; K3 j% I
2 L* @( D3 w  @1 L6 S
) S( N3 v8 t% O% n1 y& _
while [ -n "$1" ]
' n" n: {, B6 R. r  K4 wdo
0 U  F$ N) D4 o. S& i! W. ~  case "$1" in) f1 X$ S3 X2 x: l$ w- I
  -a) echo "Fount the -a option";;" h" G7 c- V8 N8 m3 Q

6 _- g, M" J( Q7 t  -b) param="$2": @$ e4 \+ g6 a- j
      echo "Found the -b option. with parameter value $param", t2 M3 n/ O6 s# u' p
      shift ;;
: d* V% }' B4 V
3 a! f% ~2 P5 j, r  -c) echo "Found the -c option";;7 M$ n5 V6 W- F' X4 H. z- F
5 I8 ?/ D6 O8 B& e( k
  --) shift
" U( I8 s* j0 e, j      break;;4 @0 t- M4 q) J0 W

: G/ e* ^- @/ T. j( n6 F  *) echo "$1 is not an option";;
: C6 [& w& u4 b' S' ~  esac- l' C& k% b( Y& A& t! h" `
  shift
9 ~4 x% `% T. \1 V$ Z7 r  done, ^3 e: z3 D/ O# E& x; R4 B8 R" Y
5 R5 x& Z- g- |  E/ X
  count=1
9 Z. [4 b5 X7 w; c2 k' R% l$ o  for param in "$@") [: f8 [. B! W- ]! S
  do
% ~# T) b+ m5 u( I  J  w. D, t    echo "Parameter #$count: $param"
) i/ E& a+ n1 g5 j    count=$[$count+1]
, {  E7 W2 d7 V- w/ `6 z  done9 p+ Q, v' J+ X
4 H/ @; n% r$ K, O- ?. ^
9 T" @$ M4 [1 S, |

/ T# d. Q( `2 E8 p
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test& p# \9 C# ^! D) K* E
$tt:   -a -c -b ''\''test'\''' --
( ~+ J" E. K2 I( b: Q$0:   ./getopt.sh
4 @7 r0 A1 P6 v; }$1:   -a
# }3 `! E. o5 O) V$2:   -c
  w& ^9 ]9 o. ~: r$3:   -b
# i3 P3 n) R5 e$4:   'test'
- t5 _% w5 B& v7 n& F" p$5:   --2 H( w; ?. c! ~- W5 ~
$6:   ! v) |9 }1 {; L
************
6 E% o: a* i$ r; HFount the -a option* s! c7 N+ q% {! _7 d
Found the -c option
$ z. y  G+ d5 n2 @Found the -b option. with parameter value 'test'0 ?0 G/ Q3 ]' \' P6 G; ?- ]
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法
% A7 T- X3 I# }  Cgetopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
3 y3 h2 M. Q5 q) t" I代码:0 _5 A& c9 s& Q) i
while getopts :ab:cd opt7 x" b! O% {3 u5 {/ v9 ^1 Q7 y
do9 s9 q5 g! H9 v# v; |
   case "$opt" in
& X+ ]% H$ H. @- g+ U/ F9 J  a) echo "Found the -a option";;
  i6 Z" e9 {/ ~5 w8 Q  b) echo "Found the -b option. with value $OPTARG";;0 M8 L* m5 z/ u. J
  c) echo "Found the -c option.";;
$ x2 p5 ~$ E; }1 H. [% }9 p) A  d) echo "Found the -d option.";;
/ H4 s6 [2 X( p1 U0 [9 }: D  *) echo "Unkown option: $opt";;
' u( j1 p7 ?- V5 @  esac7 d7 w- |6 G, u9 k( K1 U2 ?* o
done
5 f7 _6 |$ r# Q1 g' b0 ishift $[$OPTIND -1]( S6 K; j8 h2 b# ?$ @2 }8 T0 ~/ A
" D. @8 _  ]! b+ H, L
count=1- `, I! y. u8 K5 c4 m( E+ m9 O
for param in "$@"
- p% L. G' p) `- d7 wdo
/ V& c" _$ c0 z! O3 O   echo "Parameter $count: $param"
( U; B/ S4 w0 `& i4 S  count=$[$count+1]
% m( F5 j& Z$ ^3 pdone
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。6 ]; G+ W; o- `# {1 e5 Z2 I
其后就可以这样用
( `3 f2 W) a2 F% Z0 S./getopts.sh -a -b test1 -d test2 test3 test4
1 M! b$ W9 c) G: z./getopts.sh -acd -b test
6 F( ]& w$ q# T- H./getopts.sh -a -b test -c -d test1 test2 test3 % a; m5 u" B% @% y4 K8 i
等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash
3 v4 P0 O/ y9 @6 ~+ Y6 V9 p
. Z4 F1 M5 {9 _* C5 ^# B* ^
* i0 ]: P0 J) B$ T& @. Ywhile getopts :ab:cd opt
- ?7 Y- {" H$ V' r7 H0 H* O6 W8 wdo
0 w; o$ z; F# T2 h2 N% [+ k  case "$opt" in' ?; J; U) M1 E/ a1 m& E, j# O
  a)echo "Found the -a option";;
* p2 M! T: U* `' C+ C( j  b)echo "Found the -b option. with value $OPTARG";;4 H- T8 Y3 m/ s0 q$ x3 t! |; D
  c)echo "Found the -c option";;
; Q* }( @: h; F' b# z6 n% q  d)echo "Found the -d option";;3 J+ {" c1 d) Q
  *)echo "Unkow option: $opt";;
/ W! b2 o0 a$ T8 ~6 k* E' l1 \9 r& G  esac
! i% C, R4 z6 Idone
8 ^% r3 U5 }/ C6 F. [
  `, O5 w* H9 K echo "**************"3 W) ^9 @6 ~: ~8 m
echo "OPTIND: $OPTIND"1 _9 I+ x( }- e" M2 Q
echo "\$@ $@"
: D% U8 p. ]9 [" G# g shift $[$OPTIND - 1]
; v1 w) j9 l% j2 U! T echo \$@: $@
: g# j, M* x% w; k echo "**************"
3 j: Q0 ^% k  w- O' t" `  a& F- D; M& m0 d
count=1
) K2 C. A; g4 ~- i& d0 |for param  in "$@"- y/ w5 P7 f2 ~9 T( f; w
do
" |: ?1 O% Y3 o6 C5 K# p! c  echo "Parameter $count: $param"
( V, N6 `+ I: X' y  count=$[$count+1]
8 e* f$ r$ t+ {2 c' f( K- pdone ! O5 L0 o. m9 T0 Y6 R& k2 C
" _! ^4 W( ~9 g# T
) @7 V& {& b/ p  i* O
/ e6 Z: {4 ?: w9 w/ b( ~# A
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
3 `3 G' h$ r& x! I9 V
7 X7 [7 J/ x( J, R0 M2 Q+ J" x
回复

使用道具 举报

本版积分规则

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

GMT+8, 2026-4-17 16:29 , Processed in 0.036619 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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