一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4777|回复: 9

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

[复制链接]
发表于 2017-2-21 23:15 | 显示全部楼层 |阅读模式
' D  J$ S. x9 y
getopt/getopts:Bash中命令行选项/参数处理4 W3 j* r# a0 C/ G5 I5 ~5 T/ G# Z

0 C. I* Z9 a7 k8 V4 |5 @0.引言
5 [7 G4 |: E# I! |, s4 q- [& Y% {, A. z1 [% F$ ?
写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
$ L; j! ~6 R) T
( v0 U, R, O" N" a  }选项与参数:
/ d. O9 F- h" a' m6 [- t9 Q( i$ O
1 e6 z3 l6 M8 q! e9 Z+ [如下一个命令行:
' w4 u" b! I. f- \! X2 I' v$ L5 @6 d5 m; Q  Z8 c% E5 u. g6 I
[vb]
+ Y1 r; V( [1 k+ h./test.sh -f config.conf -v --prefix=/home
% r5 c: \# _- b$ w$ B* n- W' M: h( u# p, g
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
- Z# K: c! B! C& x8 ]8 A- T' g$ a- p0 S  R* j2 `" t7 n$ q
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。. P: W  ~, Q( V
: H% i, L$ t& ~# u7 V4 ^( k9 E! l
在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
2 j1 w, e* M2 n
3 o3 g  O4 N- ]手工处理方式
6 Y) P7 e  Y# g9 U
; _; E. x* q! F* `0 ggetopts
  t6 y, U/ R4 ]; k6 k4 O; O
" r9 Q6 Q/ j' `1 g$ Ugetopt  n+ ]( f, ?4 r; q. h* C% x
) c) N% [  ^1 I8 z+ S% ~
下面我们依次讨论这三种处理方式。
0 O. F- u1 D6 j6 q( U9 A/ _- y, v+ t: O5 S. k9 y5 G
1. 手工处理方式
/ M9 T7 y  D3 R+ S6 F) c1 E4 C$ ^! `' B9 g$ O( {
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:3 q/ c8 B3 K  T

; a9 l# s" a3 P! T; ~4 y$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]. a1 v. t& H: j8 d
$1 : -f,第一个参数.
& B: w0 }% Z& l3 H7 i: ~; F3 m( Y/ ]  i2 P3 a4 a' Q0 _$ `" ]
$2 : config.conf
9 ?0 u3 d. }% F$ Q$ d, M. K* R$ b" K# ~
$3, $4 ... :类推。
' v- W8 P- w) Q! p+ P3 b# F" i5 k4 Y0 N( ]  }* }
$# 参数的个数,不包括命令本身,上例中$#为4.# W3 K" j+ O& i4 k8 {% d: H/ R+ f

& x" R5 ?& z* r2 M& x7 m$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
" m( d$ k7 d8 n) x( |$ R( p
7 |; y. g' Z  L. T  e$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:! h5 E  q4 J) w9 A- M! b
$ z9 Z% a9 B; \, B% v5 Q8 f& S+ }
[vb]8 @6 l2 t7 ?: p  z6 V; I1 E. F
#!/bin/bash
$ x/ l  f) i: H- B. d, X  [9 Q+ z" Z6 e/ R3 ~" u6 L2 k, a
for arg in "$*"
6 x: E' P* g( }9 c" e! u7 O# `& G$ P9 B0 Z0 R
do
6 O/ l2 K  p2 c1 V8 H; s( ]2 t5 L" d7 n. H( \2 a
echo $arg  h8 y8 x! g, f

. u' \, Z& F& E8 o0 {5 ^% Odone
  a8 g% u% ~* t- g% c0 G* D2 Y- N/ Z  M
for arg in "$@"4 K* d; y3 B# Z
2 ^$ D3 S0 B) p% o! o4 \' P. u- k4 L
do5 l  L! e; J* s! I) S9 w% Z( L% k

# v- o! n( H" P2 U. r: W! h) Lecho $arg8 G% _7 Z! u0 c9 {
" J' i  D2 ~3 ?6 w. @2 D% Z  e
done* Y, N; N* g2 `% T0 s+ C
' J3 A3 [6 B. {. l
执行./test.sh -f config.conf -n 10 会打印:
2 K% H) _7 X. j- S
3 d9 X7 B/ \3 j: a-f config.conf -n 10 #这是"$*"的输出- X* j: X% c. Y4 C

8 v! Y% V8 s3 e% t#以下为$@的输出" a# p: n. F0 R& i( r( l8 {
: h, B) `; @: ^6 x
-f! Q4 q- @6 [! z, l

/ l$ p4 U2 Y$ Hconfig.conf
  @5 f& u- R6 b7 `+ O
8 {% x9 ^$ G# O  C! a-n
2 ^+ T: G) f. P6 E& R# r/ S# T# A; \) ~2 C8 \+ I& z
104 f" }: a& @, \/ v7 X: ^2 _

" B7 ]9 g0 M2 e3 [- I所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
  B) K; y3 ~2 H2 q5 {% @" _$ N2 S
. f" k. \# j0 S% ]“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
$ k" R3 \/ o, y' W. v9 V' C+ R& M% ?) _4 q0 u
[vb]
7 \9 ~& C9 ^+ |+ a8 t# W#!/bin/bash$ N% \! G4 G3 x/ d9 Q
' _6 R: \8 U2 }' R/ c" M! K
#if [ -n "$1" ],参数不为空 - ]3 j9 _* \- r1 v
if [ "$1" != "" ] 0 v5 ]( k# Y' n% x% Z! \& [! Q
then7 X4 O- J" J! P% o0 U5 N$ y2 ^- m
, i7 l7 q: w  H+ O5 c' p6 s
#...有参数: P# H4 Q3 G2 W; `4 `
1 d' l0 M2 {; O' X* U' O2 n
else
; x- i( g5 g4 k8 b0 k1 s) f
. V" n; t, p' D# X7 S1 hthen! [8 l# j  ]! P7 _. b( X
3 ^# u2 [9 I. j% F2 e) d
#...没有参数
% Y; d& [* \6 \8 i' ^% p' |* ]( p- ?( }7 c3 J3 g  s
fi
) Z4 d2 O; Q4 }" K0 o1 {5 n4 G' Q2 m: @. t! O% s
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
% T# C9 M2 w# u& b7 ]3 w
4 b* ?) W1 J; g7 X8 h1 j2. getopts/getopt
2 `3 x1 C8 D' C# O4 |! X4 C! `: W2 H  o' I8 ?
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:
- e. U6 m$ \8 N# \& f/ L, A
, c# U8 ~5 j# x. `$ L./test.sh -a -b -c : 短选项,各选项不需参数; q2 x" g, V" e: ]+ T  W

/ Z4 W1 W! ^8 J+ b  d./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
$ ]) M+ Y* L& y5 b: |  U
+ A% v* T& W! i./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
. a) `' D. k" L0 B: K! X$ w% z
, C( ^, L. S0 w7 M' w./test.sh --a-long=args --b-long :长选项
1 h1 t( x! E+ \( g0 I: Q* h- B* G
; B3 Q. N9 F$ d& L1 _我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
. N+ F" U( d5 f1 F
4 U: A* h$ G8 z% P( e+ r9 E[vb]
. d2 ~0 U. F) e, I#!/bin/bash
# N! u- J) \' X0 `# D+ F* ^2 r6 W9 b8 ]" e8 a& Z5 _& A+ f
#选项后面的冒号表示该选项需要参数
8 \9 y. H, E% {8 A
4 f% j3 Y1 x- x; zwhile getopts "a:bc" arg2 l( |- q/ d" g2 C0 v
$ a6 O  I' }* z% @% @' }
do3 W) y- T+ ~  E: M$ J& {- \; z
- c* C. f! s, ~& X, P
case $arg in5 o/ y. G; S& W2 W

* ^( b9 N* P; w8 M( ra)
" c+ l, Z6 H6 j) ~% G! Q2 J4 s7 M) g% e& c
#参数存在$OPTARG中
  W- e! Z' J" p0 R  X
& O& A* }! w! u* g$ v0 M8 yecho "a's arg:$OPTARG" ;;
0 ?9 R: O! J1 m; H# O
3 H# K, t' ^+ X( T5 ~b)
$ F7 R% e) d9 u& @& y4 X+ F! o4 \% k4 ]' P- X5 `
echo "b" ;;& w3 C0 p# N1 _1 ~. G

, v' R; `: E0 x) O& E7 ^c)* Q) c# t2 S8 }. E  _) H6 k

& V' x8 g! P* t' m9 k0 Mecho "c" ;;
" h7 y8 K: ]; e* `3 y. R3 l2 d# K+ k  ^! K
?)0 m  v1 Z% u% R- o3 h7 x

, h/ W1 d+ O0 x# I# w7 W6 S. D#当有不认识的选项的时候arg为?' E4 q! S2 z8 C/ a$ [
5 a9 `. y2 o0 C. |8 S6 f; _0 `$ P0 M/ M
echo "unkonw argument" exit 1 ;;
5 F6 q& l' L6 q  \! @$ y7 @3 U& I" I; I* r, F! Y
esac
: y0 O; e9 n+ m2 z
( ]% B8 G8 V9 `* S5 X: e8 sdone
# o4 I( q+ y0 F0 i$ e7 K! y) L8 Q. `# R- b
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
" Z2 C7 |5 T2 N+ u
0 W% X! V+ M) G' c来加载了。
) G. Q% M$ O( x) V+ i# I6 V2 m+ b: `2 t! D
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:# \! E# I0 x# R' _% y7 ?% @3 I! T

- x( t7 f& ~- A[vb]
8 Z5 q8 ^( a6 H+ v) K#!/bin/bash% L7 {. q/ W# M

: Z2 x, c0 R9 z/ T$ P1 f: a! `# A small example program for using the new getopt(1) program.
, H4 M5 D0 ~' M$ [6 a" k. d8 e- C6 p  z8 M$ }2 h1 Q( D% ^4 X
# This program will only work with bash(1)
% {1 `- F4 |8 r/ R6 |$ _
8 u& e0 n  x5 U! ]- b# An similar program using the tcsh(1) script language can be found
4 {+ b2 O8 O* }7 x5 K2 Y9 j- ^0 [. w, _7 Y# d6 v
# as parse.tcsh8 y' F3 x" T1 W& J+ b

9 f, h* r) L4 Z3 e1 Q. z: o# Example input and output (from the bash prompt):  `8 m% R, `# {8 e+ t2 ~5 E% n) Z
& ~3 v: a0 i3 I4 z2 h
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "+ J- {6 G# g( Z8 H* `+ t
: u9 c% T9 l) u3 a$ t
# Option a6 k8 x) Y0 B  H. d3 g$ H
( h9 e$ R' e" N
# Option c, no argument; G# M/ o% p, t& \8 V; W3 ]
+ V4 D3 H8 r; J; j% R) ~5 q
# Option c, argument `more'1 [: O, x* r& K
& U1 \2 Y% y2 X* a! l2 G4 D
# Option b, argument ` very long '& o% W7 U9 ]1 D* K" J' C0 C
1 g6 C+ U6 i) z5 P
# Remaining arguments:
; |5 A+ u5 y3 @5 W
, p3 _/ \& R5 a/ i3 G7 g# --> `par1'
+ s0 f0 @8 ~+ W' ~9 P+ y) ~2 Q, n1 ?' N' y
# --> `another arg'
" U+ o: I3 |! g! x9 |, x) r8 l: s6 h9 P2 z) H0 h3 V6 P
# --> `wow!*\?'
. ~8 s$ }. r& U$ |
6 y: X0 J/ O% i4 y6 j2 T# Note that we use `"$@"' to let each command-line parameter expand to a( G! r; p9 i7 x
# ^" V4 z4 {0 a4 |6 w
# separate word. The quotes around `$@' are essential!1 n" f% b0 ?$ S7 x, @/ b6 J7 c
/ }4 H6 h0 m; I% _6 ?$ ?% v
# We need TEMP as the `eval set --' would nuke the return value of getopt.# U1 x9 |- Q9 T. q& m; p: M
) c1 e; B5 R  I$ G
#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
5 y6 H0 }. L  M9 y, ~+ A% L: H/ O* r3 n, K& Q
#如-carg 而不能是-c arg" i) B# M$ s  G# z4 j9 L
; R1 P. I% a5 r5 T1 ^( ^
#--long表示长选项; f  ?5 f/ l) ?6 ]. {
4 Y% r! Q3 A( m' [3 ?
#"$@"在上面解释过$ T5 o' f0 j! h6 s% F) C, D6 r

" A- a5 E' l+ y) P- H; r# -n:出错时的信息6 j- l' u. f0 i# C' @

9 F- \# d3 o$ G; d/ E9 t$ m; i. p# -- :举一个例子比较好理解:
2 {# V. a6 X- G7 ], v/ \4 R. r% j0 |! [/ Z; |
#我们要创建一个名字为 "-f"的目录你会怎么办?' a) Z' j- E4 T0 }7 B- Y2 N8 [

1 @2 @0 q! \9 \* n& n! y) L# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用7 ]2 G5 @; Y4 ^& t, [; O

. O$ M0 }* c+ p. y# C6 a" Q# mkdir -- -f 这样-f就不会被作为选项。
+ F: @& C5 o& D& |+ A: ~$ q; ?6 D4 H( q& X1 s6 @) c4 A$ \) }8 T
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \7 z6 O7 G3 V/ z+ f- X( }6 ^/ @+ T& g

, U: P9 x5 y! s, `1 L/ x% F-n 'example.bash' -- "$@"`
2 R# t' g- j- q. @' E7 U, M) g  J+ B6 y* E
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi : \' {+ a8 `& J0 l" J7 b
# Note the quotes around `$TEMP': they are essential!
" s/ L2 i& l5 O) z
2 O2 I6 t6 S5 d) W; D#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了
5 g( }5 W# i, l% o( z: k4 x4 @2 j
+ H! B  g- Q; u9 d. P( U3 m* `' `eval set -- "$TEMP". p" B0 Y5 ?9 B

3 a/ B# Q; f! S$ H#经过getopt的处理,下面处理具体选项。2 k6 _# d0 Z/ n- W) |7 k  D

" ?3 s' W* f) awhile true ; do
0 }8 f$ g. L" M8 E9 y6 `+ e2 u1 }9 \$ e: Y1 b( R
case "$1" in
4 X6 Q- S' R1 R4 [
2 q  q7 l5 T9 y3 I( w6 @. a-a|--a-long) echo "Option a" ; shift ;;& _" @9 x, y5 _9 g

) {" E3 b. X1 o/ p( H-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
* Y( b$ B8 b: L0 `/ I7 l! F# p$ ^& @/ ~4 ]6 u! |: q4 a: _
-c|--c-long)
5 b5 K/ D  H/ x8 b. g( h
  H* g: ?; f0 I4 Z1 l. Y# c has an optional argument. As we are in quoted mode,/ E* O" K5 ]3 f) o( f
7 A# f  E' V* ?5 Y) y$ B3 E9 A
# an empty parameter will be generated if its optional- \& X  c  a" N. b4 ^
/ a! R5 I3 @. B1 R- F* F# |
# argument is not found.) j( l( C* j0 n* h2 g
& z* z6 K% ~% J# l! x' B9 d7 Y2 _, K* I
case "$2" in% Q3 [  ?# B+ y7 e# w

. z5 i  R0 [1 e"") echo "Option c, no argument"; shift 2 ;;
5 H. O- `9 M5 K, u0 Y. Q
9 d/ |# \9 }& _6 a" {*) echo "Option c, argument \`$2'" ; shift 2 ;;
8 V5 A; }  f6 _4 K' }# U
7 q# c: L9 w# [8 W* _esac ;;
- v3 a6 Q. r! w. p1 k" I- @4 O" a* k% i
--) shift ; break ;;
% g7 C# d) C4 \5 E/ l0 g& ^$ A9 R$ F! o0 f
*) echo "Internal error!" ; exit 1 ;;% h: }9 L. m% m7 H6 ]
$ z9 O, ^! L+ ~6 z/ E
esac+ P8 d! v; v; p$ X, ?# y+ _$ z

) P  {# y1 x. I) s3 H: ydone0 _( ?  y6 O( W" K4 y
5 [4 F  Z/ k2 J. b
echo "Remaining arguments:"& T# J8 X: B* n, p" f
; B$ a) c) Q! L1 q( x
for arg do
/ B" o+ z6 t+ h% t* v7 h3 X: X2 T8 ]$ Z+ p% W# X( `# Q( O, l
echo '--> '"\`$arg'" ;
8 m) Y  K: i& D7 b- f# W3 p, Y, Y1 k
done$ S: `# T1 \/ M2 j$ j( e/ ]
- \; H9 B2 \. x. I: }$ r

6 w2 |) {: K1 r6 j比如我们使用* y  Y2 q, ^" [

( ~& j- _" Z, ?./test -a -b arg arg1 -c+ S+ l( P1 B( _: H% r: D) q# W$ t3 b

; U0 r2 k) f7 T你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
" L# d" w! e6 U+ ]8 A7 {0 d, _1 s% `( m) C
-a -b arg -c -- arg1  a% L; I6 {5 Q8 l- j1 H/ c# T- ?

0 j# {7 R; p& P3 d$ M" k! c$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。- o0 h8 S8 e0 C7 W

* R0 d% }; V8 D2 P7 n# a+ l$ f3. 总结9 e! Q- p4 v$ J

, Z7 B" F$ f% c/ }. K' Y豹尾。8 i7 h% P+ t. k2 ~) y

$ f( P2 y9 _# |8 j) n本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
+ e" |4 i! J" w, o, R0 b* I/ d# F, V9 |) }' F: R
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
' T0 N. o  O# k: s记得getopt常与shift结合使用,while循环一下就好了。

- K9 c* ^7 B' M请教一个问题' u$ J' Q) M8 O( P& L
有一句 :set -- `getopt -q ab:c "$@"`
, T  e$ V" `4 D! R请问 这个如何解呢??! M" K! Z  J/ z2 E
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句% F7 }& e4 E$ [( z9 w' y
set -- `getopt -q ab:c "$@"`5 ^/ B6 g: b. x2 B) w& q4 ?
while [ -n "$1" ]9 r( l0 N) l' f& m" n5 i& u
do
8 O* g- @* `; H) f. ]1 k% C" r  case "$1" in
# p) H; m+ C+ m* Q8 @9 e  -a) echo "Fount the -a option";;" X! R- D! E- |0 `
, Y" I! H; O0 T5 a; \7 I( e
  -b) param="$2"2 G8 o; Q6 |, h, k. S9 o0 e& R
      echo "Found the -b option. with parameter value $param"
, X3 \% O3 t' |5 U6 Q      shift ;;
; }% Q# h" @3 y  Q: Z* `& l. p$ O8 x7 v% c1 a9 n5 _
  -c) echo "Found the -c option";;
7 N7 I" f( {0 U! {8 t" f % ~* X: `" E! [' }
  --) shift
& V) f* b8 D: t; p3 }6 N      break;;: Q; F4 H" Q7 j% Z' Q, m* \. ~
* c, ?7 W  B6 g+ k/ w3 |* S- @
  *) echo "$1 is not an option";;
2 u5 H7 g& n, h! l# U% U- T9 `  esac
9 T9 c% I5 ~  P  shift
% p6 x8 _& L6 s. {& K  done
& X% _6 s9 }" [
6 r: M' E' r$ Q4 u8 O0 q  count=1
3 A/ g6 D- D9 ~7 Z; V3 B2 e/ z% H4 I  for param in "$@"; i' \+ \$ ~0 n; h( a( w
  do' ?6 p8 f3 l, Q, x& V! }1 L
    echo "Parameter #$count: $param"
; S& I& e) U+ j: d+ ^7 n. r    count=$[$count+1]2 ]5 k( l0 O% o8 |- }: e+ O2 n
  done5 ~! r* k. r/ U: D$ m7 ?
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39; X8 A1 M; ?$ v7 ~& D4 R
请教一个问题
$ F' f- N' }$ T6 B% K' J# Q$ s有一句 :set -- `getopt -q ab:c "$@"`+ v8 E5 L  C0 F$ k4 D* ~: N# ]2 q
请问 这个如何解呢??

. Y  B& B+ S( p# L) y$ }7 o5 k% j请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
, d1 r+ n5 [$ g
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12  j) _9 W7 s- J. ?( ]! D+ @, h# L
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了

' Z* N8 x' j3 N( P呵呵没关系,大家一起学习呗。+ d# Z/ m) _" r( U
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F( s: W1 H1 X8 h9 }
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,
# v; M: G; k" z0 [: z1 ^所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
9 i7 u0 a' h- f: y, ]. A如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--! q/ x0 n3 a7 z. ]6 d3 H+ U
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
- l; H0 F: h5 V5 }. l8 o7 m补上昨天调试的代码
: u3 Q2 v9 e- g3 {  F7 |. E6 p" n  C" {( W/ X9 E
#!/bin/bash
; e; X! C5 I4 I# V8 j7 p6 D' s1 Iset --  `getopt -q ab:c "$@"`- J; m5 A8 A# d' v/ ~
tt=`getopt -q ab:c "$@"`, f- \1 ~% ^! P0 d3 r
echo "\$tt:  $tt"
5 Y# I2 s5 |- E, |+ Hecho "\$0:   $0"
  X5 @5 }) X: z$ cecho "\$1:   $1"
$ c; K8 |% J3 gecho "\$2:   $2"
! P' _- _! r" Z7 h* d' V; M8 becho "\$3:   $3"
% w# x3 i. Y, K+ [; @% s8 l3 d0 aecho "\$4:   $4"( n! a! w& W' h: {6 U9 u* U
echo "\$5:   $5", N3 q* L+ G: E
echo "\$6:   $6"
" \* I+ J& v8 _. c2 r( Z( Lecho "************"
+ }/ v* G# u& `+ D1 `( V& b' Y0 ?/ U/ G; t

! S5 ^: U" {* I4 d- ?6 Z9 |" q( r$ U8 u0 _' L0 x# x
while [ -n "$1" ]
7 ]/ o6 e& P: k+ |do! C9 ]* ?! z/ K/ @, t  W' W' e5 ?
  case "$1" in& d! R6 M9 i% s9 W: P( |8 l
  -a) echo "Fount the -a option";;
# e& E9 r# G1 i' \% M( J7 M0 C+ j* d4 T
  -b) param="$2"8 T1 y& L; L; i# G7 o5 h
      echo "Found the -b option. with parameter value $param"
4 Z+ y3 h# E4 V! T      shift ;;* T% z& ^; y8 }1 {- S

+ _( ~2 l8 x) s5 }2 i  -c) echo "Found the -c option";;
/ W8 W* [0 t  K  y+ _: M
) G, e2 j$ c. w% O- _8 }2 c1 q5 W  --) shift
9 I& b; w3 L+ C. b; m$ c' j+ H      break;;
+ ~. B; ~: o# I9 X4 h, m6 t+ `' y6 M, @6 L& o! k' A
  *) echo "$1 is not an option";;' V4 n) C% P. ^
  esac
4 s$ j* i- K2 M; r# |  shift9 |9 Z1 G1 S, s; b
  done
7 ~2 h" G( n2 m, f
# \0 r' [/ h  ^" u0 p9 v& ^  count=11 w5 P1 d% [! W4 i1 B1 [/ H
  for param in "$@"
3 R- \: l. g4 f2 p. O0 N. ~- d  do
7 ?7 P' J3 I, C9 i$ g    echo "Parameter #$count: $param"
; c9 B8 m& E8 A    count=$[$count+1]
% ~5 ~- J( ?+ H- I1 U6 I, s  done
/ o1 ^( W! ^4 D6 @
+ O5 O0 r6 e& h  L! e* W% j1 r5 Q8 _! J. a7 O4 o

+ m2 T$ a# Y! y. k! {5 k
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test6 P0 u: N/ G2 s
$tt:   -a -c -b ''\''test'\''' --' n( r9 D4 H/ J4 O( d7 ^
$0:   ./getopt.sh/ q, a; W' U1 `# d/ p- z( ]
$1:   -a
6 i- k+ b0 v  t# H' b$2:   -c
7 K: G5 s  m( ?7 j. ^  r0 a$3:   -b' P( L2 u, U, R  M# Q, C% ~7 N& ^
$4:   'test'0 Z- h9 }+ {& h  ]* G) A
$5:   --
. u& ]' H& \6 o$6:   # ^% c- ]7 o8 D, f1 }1 T( C8 ?* j
************% P+ x) }( j9 k
Fount the -a option
8 Z; e& L: t  n% H0 ^Found the -c option
3 s8 k) B( A8 R# r; U5 k/ u: KFound the -b option. with parameter value 'test'
5 o  e# p+ s' q/ j1 ^
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法! n+ U" c5 K+ B8 ~. ^' c: C& p. R1 \  @
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。7 Q- X% p9 w; H# f, r
代码:& G0 {7 S* ]2 g& z  f- t' z
while getopts :ab:cd opt
1 y& Z3 j& ^( k+ V- Odo6 T7 m7 w$ `$ M5 K' ]/ F  z9 }5 A) e
   case "$opt" in
3 |6 i6 z' w3 U6 p5 k  a) echo "Found the -a option";;
" E9 ?3 c* n2 P3 f  b) echo "Found the -b option. with value $OPTARG";;
% K* |" h6 i4 G4 y9 z0 h5 n  c) echo "Found the -c option.";;
8 w/ T2 u2 ~# T) Y: }, x2 t  d) echo "Found the -d option.";;9 u! g/ ^0 v) A% I3 a# V/ s
  *) echo "Unkown option: $opt";;8 w/ L: |/ N2 [& W! Z
  esac+ ~' \9 \% U) ^1 m7 {, D4 o; \* `& l1 k
done
3 ?% a, s' m: y, Y: Ushift $[$OPTIND -1]
& `2 C5 d1 g% l8 `: ~5 f3 O, e- \6 o
5 g; K& n" N1 I9 v( S, L# Ncount=10 G8 ^, U& C+ B* Z! `( F6 ~
for param in "$@"8 K% ~& [) \# f) b- u( `
do
- D7 v6 S( O& T, s6 E- ~   echo "Parameter $count: $param"
4 ^% v8 k( r' X$ D, ^- v2 }4 O# t  count=$[$count+1]
  k( v. u0 e- D# J8 S+ Pdone
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。+ H5 e' I. ~7 |+ a. A8 H
其后就可以这样用2 \6 E+ `7 ]4 x0 H/ z
./getopts.sh -a -b test1 -d test2 test3 test4' b; Y  x6 P0 z. ^- m. W1 N
./getopts.sh -acd -b test
3 ^* E2 r4 I# Y2 e4 w, W./getopts.sh -a -b test -c -d test1 test2 test3
: E$ I  N9 a" \2 v+ W7 e等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash4 Q. m" q; W5 i: ]

. t) K7 z2 M$ Z1 G' r# i
. E% W8 g$ f; I6 n5 r# bwhile getopts :ab:cd opt
" F8 A% v/ M$ U2 qdo+ B  n3 P6 C6 I9 B/ [9 g" W
  case "$opt" in: i- `) [, U' [
  a)echo "Found the -a option";;
5 e0 @& u7 P* l6 S/ y3 B/ r8 k7 |  b)echo "Found the -b option. with value $OPTARG";;' d+ W$ H$ Y- b" e) u/ J
  c)echo "Found the -c option";;
( b- y" \& R1 r6 ?3 R: F  d)echo "Found the -d option";;) t8 o$ d( ~' J8 b
  *)echo "Unkow option: $opt";;3 e- L1 K: }, u  M- D7 B
  esac- d' s  P- g0 t8 ?  a5 U5 s
done
! H, _2 n. \; O" }/ o' J; p2 @% ?- \
echo "**************"
) V+ V, Q& n3 b9 @7 B* k1 z0 j* L; Z: O echo "OPTIND: $OPTIND"% t9 \8 m% W7 T1 b+ x7 U
echo "\$@ $@"
$ E: e/ |4 `8 l% I$ Q4 F0 a9 B& p shift $[$OPTIND - 1]
6 s) e4 W0 o! Z0 `; c3 s2 ] echo \$@: $@! L$ v7 F7 f6 h  o# |0 N/ a
echo "**************"
, J4 U  M) `: [* h( }# @2 t1 e9 b/ m3 Q& l0 C6 x+ T
count=1) U. {7 y6 g& Q' [# m6 d/ e. d2 S
for param  in "$@"
6 e! I& a* E7 P9 v: |$ O. tdo+ A2 Z0 q. P8 W, f/ ^
  echo "Parameter $count: $param"
- p$ h2 U. g" l' e8 D! ]* l& j  count=$[$count+1]/ D" h" _. w, b0 `! X
done 7 [' o; Y2 \" G; @( N& c

+ {0 S7 ]1 D! s, P7 ]- @9 x0 |- ~7 \' c( w+ m* _$ O# D6 ~; ^2 ?1 a; {# ~& a
0 z6 X) N. }9 d1 E5 Z/ s) q
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
9 q1 _0 c) d  R
+ B7 K. m) G& |9 B
回复

使用道具 举报

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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