一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 5282|回复: 9

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

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

- V! @! t" i2 c/ v- N( K  Lgetopt/getopts:Bash中命令行选项/参数处理: l/ l- n( n+ X& y$ t1 l
2 A, @/ I; ?! D3 U) I0 }
0.引言
6 e# ~  Z! a1 {, H0 p" n! p  L& K& g  c
写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
! z# u! @& e* k- \! e, ~% [) t/ B$ T% H" L* Q4 X; {
选项与参数:
8 d$ D- t. o$ {: ?# w0 r9 `/ V+ i( P/ d/ |
如下一个命令行:
& @& u/ e4 l. L. u6 M- M+ ]; H8 }( y
[vb]
5 d$ @- N% o$ Q: `. v# J0 M./test.sh -f config.conf -v --prefix=/home: ~" T8 L  o5 q* H# p/ {
! u9 [  }7 k+ {; o1 I
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。3 a+ p+ ^5 @7 Y4 T9 f3 C/ t- k

2 G* j! @7 }1 a- F" e2 b) M! X--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
* N6 V- e5 r4 p6 {- i& k. g' g
+ m8 P, X; }, `4 w. l在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。% J$ @" t, r6 B
3 A/ H: `' i) R% u" W1 T
手工处理方式! R1 ~5 m- B- v1 G5 l1 A

+ y3 y/ n3 M& `7 ]5 i7 Pgetopts* V9 _+ e6 D% K* L- {! Q

% w) w4 q8 J  i1 ~7 ~getopt
- M+ z* F! c" v8 S+ M- a! l9 \  X* M5 W! [8 M1 m6 |( H
下面我们依次讨论这三种处理方式。: O: x  Y; }( m3 U) R: i# `

* m% U# `' h9 r( x1. 手工处理方式  M( M; ~% k' ]' j$ A1 x1 d  W+ _
, r7 [) t; I5 P5 n" V: a7 R3 {
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:
2 f/ n* M- y; Q2 U: X, `
9 u5 E) ~+ ~( a. I+ u% N0 Z$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
1 I1 g7 O3 Q. G$1 : -f,第一个参数.
2 u0 O+ \3 u* h3 S$ T# V: d' o, m' v) e: v" X# k% @  [' g
$2 : config.conf9 W' W$ V6 D' P0 ^  P; y5 ?0 L" O
: \$ k* x  Q, O$ s0 K
$3, $4 ... :类推。0 n4 E$ d" ?) W/ t: J8 L

+ l; l' n. G2 M% G$# 参数的个数,不包括命令本身,上例中$#为4.
5 `) H) {( Q- O4 B6 I- V% \  I9 [# N( N8 {: o; }
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
0 o+ k8 b& T% Z$ M6 @* s  q9 q& m  r4 F- Y' l, a
$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:& v" B  j' O9 A: b9 J

3 u9 x6 a) g  z) B/ |0 n[vb]
2 I" c" y6 ^! b. S/ ?#!/bin/bash
6 V& B' A4 D' v+ J8 _4 F
5 X9 h9 t- l- C% lfor arg in "$*"
$ ?, H& @/ Q. y! b, ~4 @: [! D1 T. t% y
do
# y8 U9 g2 W5 C3 x- y  |( X. }+ Q& @; t7 R
echo $arg
) r8 w: I  o% n6 c7 L5 \+ Q- H. P& A3 u0 O
done
3 r; V- R' D& v5 t" v) ]
$ U7 j9 R3 t$ j( [0 S$ b7 dfor arg in "$@"
" c" s1 j5 V* l) w. G% s$ q; T- O  _+ ^5 a' p. b4 p3 O
do
6 x+ k" _) p7 F0 r$ P) N3 n+ O: Y3 E
& P* H; O! [2 decho $arg
" f# Z% A  v/ o* s5 F. `; k6 m' @9 Q( k& h. d# ]% w/ Q
done% f- b0 M* l/ B! c5 x0 _$ _

! G; k  c7 F  \7 \; ]执行./test.sh -f config.conf -n 10 会打印:+ D+ x. M' F8 `' ^  N
" m# V, }% ~3 ?  b4 W
-f config.conf -n 10 #这是"$*"的输出
# N6 R! j2 n* @3 m
" `( m% y2 q2 f, x9 b* S#以下为$@的输出
2 n4 H! D" u! G7 t$ b
' L/ e- ?) N9 p8 u3 {) y' t* Q: u1 F-f
: D) r6 f2 M3 k. E
( K  z2 F* ~4 _/ b0 @config.conf
, l( W  r& _$ z$ U2 E
% @3 ~& [) F( L9 o0 o7 j-n
+ W9 A2 ]5 {/ H( D: N
5 h1 q2 U  W- n, ?* B' b5 C10) g3 B( p4 c( X$ T! P6 E: C

$ m$ ?( Z( J1 S6 R所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如6 k4 `$ o& k% u% M! E# |6 ^
0 O& H1 q) I( N6 O, A4 c% f
“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
2 y$ `+ B9 H3 ^  R2 B" m9 ~& o! T% s5 R
[vb]
" M5 Z5 y4 u# n2 h* W+ J1 O, R#!/bin/bash
" F# N' Y. e" u# A( ]( b  [. Q
6 D+ R% i& `+ u#if [ -n "$1" ],参数不为空 4 f- P, t3 Z( [/ _3 a$ e' c
if [ "$1" != "" ] % H8 O( M8 V' T& k( d, o
then; Q6 g) ?6 F: Z6 z* i

& d; \( Q/ W2 g( x5 n4 L#...有参数; u0 ^' L% l  x
+ e2 ~& A. O1 E  [1 ^
else
% Z2 U- c4 q# u4 s  ?0 V
. w8 U" z# m5 b) K/ ^then
) U: V9 `: Y2 t2 S1 Z3 f) I9 Q' }( l; [/ \7 D; W: w, w. q7 R
#...没有参数  F  `, X/ T7 w

, \, T9 l- f% V0 T: ifi: ~( P/ M/ y+ ?4 `. Q* s

2 o, Z& W, P7 e2 k: b1 ?手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
- H, C/ w" l) F- O# b
8 \( A) ?: |' }* _, n8 @; J2. getopts/getopt& Q7 u. y3 m8 j8 {

7 O2 W  c$ s; g: v- n) O8 C: Y/ g处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:
  @4 ^1 G# N, x% t) u9 G. S4 T& u3 l1 y) ^5 V' E
./test.sh -a -b -c : 短选项,各选项不需参数! J8 _% J% [$ |, q7 r& o& a" T

2 S1 P$ ], o6 ?- k5 B./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
- B! A8 Y4 N- p- S: [- q7 Q; p- I5 I. p9 J5 I3 ]3 |5 q
./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
1 n/ U8 q3 d, t1 m" O* r8 ]* ?5 q4 f6 t
./test.sh --a-long=args --b-long :长选项# D7 N3 }6 S2 R. V3 O4 l0 `0 Q
5 k) Q  t" I% m6 C0 D( o. Y$ U: X* J
我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
: Y: M  S: j% C
; M9 P* r" K) x: E/ Z7 q) _, [[vb]. V' F+ \9 a2 X4 P* u& X
#!/bin/bash0 u* I- S6 W$ m% l4 `

+ V! i0 l4 I! O3 R7 z, X5 U#选项后面的冒号表示该选项需要参数
! K( m( q4 r& J
1 Y( ]( C) R7 Y1 y2 A/ }- Ywhile getopts "a:bc" arg" M; }3 M5 Y* L' C' d

  q  O9 X7 h3 K" z3 E* xdo
% ~/ R) L& C! W! L! P3 \  x5 K/ e! y
case $arg in% J0 P, r& [3 g

/ p7 n$ F8 I6 n! A& y! k8 Ja)7 R% }" Y7 i6 D: ?

- F$ R& a3 X8 J( B#参数存在$OPTARG中( `8 u2 B! d, b5 w

7 ^9 ^2 b3 A/ b# W4 zecho "a's arg:$OPTARG" ;;7 f' f+ v3 B, u, n5 _' {

+ _' k0 Z- |: E/ o( \+ c/ z% d9 g9 @: mb)
, F) N! M* R/ T3 ]( o
5 o" }% ~# m7 _7 Y4 a# secho "b" ;;
5 v. n& R6 E! w! l* z; u5 P2 `+ d% z
c)
- {* x) v/ F! D
( p, x, A! L7 d3 a) q% V2 j: E  x  recho "c" ;;
. |+ A7 o& v) e
* }  J' W) ]- a3 k) R$ M?)
3 v- W! j/ [9 S. w+ s/ ^" C$ U3 w0 u% a3 {6 y1 s
#当有不认识的选项的时候arg为?: P, v; |4 G& |) s+ {2 t% v, ]

* \2 x- V" U* j5 Q' Fecho "unkonw argument" exit 1 ;;
( [% C0 b: w, w; E' T6 W6 t3 H
* J: }% \+ h! |% T2 R" {7 t) Iesac
7 o! o- x$ A9 e& [8 a0 y
( i4 L7 ]- y  E1 wdone
0 `( i! x/ ]8 c0 A6 D- j4 g- Y2 k- u/ N, g3 F
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
; J7 B* i) H$ m8 ?. n
3 f$ R+ L, U2 z4 y) h来加载了。
% s. ~/ e' g& d% [: h1 H" K: Q+ b6 p% D7 a' W1 ?2 e& Q
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
8 e* j6 Z* x0 B+ ^3 Y  g; `5 L. ~8 g
[vb]
4 y8 E4 v4 V7 D* v8 e' _3 F+ n#!/bin/bash
' h- T3 @4 E. ]! t
( e! f! g: \! Y4 }# A small example program for using the new getopt(1) program.
8 M# O( O4 {. F: p5 G1 L* x& j  {4 u: d
# This program will only work with bash(1)
. f7 b' a* {. [- a5 G" d; N7 Z" t- R
# An similar program using the tcsh(1) script language can be found
4 }! Z* F8 s; e( }1 s
" [; a6 R' w* J4 Y7 a# as parse.tcsh0 v+ i0 Q! t% a+ }, Y  K

1 r$ C$ x: k2 \0 k% O, Z# Example input and output (from the bash prompt):
1 c4 P/ G9 l9 \# I  r
5 \7 ?4 \, N/ P0 E) p0 N# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
; v8 h; r* E1 \3 M% f
9 q+ I+ j8 P$ R' I# Option a- Y; d7 |5 l$ w

+ b$ s- i! j" u( o0 I2 d, I' R# Option c, no argument& W6 A% u+ v+ i  g% R

, D' c: h, V" y. |, Z# Option c, argument `more'
6 }- h3 L6 I4 i' E3 G9 ^5 [: y: o9 i5 o- F- b! J
# Option b, argument ` very long '0 ]) D+ w/ U" U" T8 L
& w, O4 R% m3 {
# Remaining arguments:0 L: w0 c8 j% t$ V; k
! _0 A- c8 t9 z! [! v! s" \
# --> `par1'5 X8 n7 `7 N5 o9 E; L

" o, ]8 r- p. W+ A# --> `another arg'7 @- j; ^1 D- _3 e0 X1 F  D. I& I

* j. i% u% j0 f. B  l$ ]# --> `wow!*\?'4 r1 S7 a1 ~6 A" w! J- Q/ a2 h2 _
9 f* V5 P' N3 E" `+ w# I; d
# Note that we use `"$@"' to let each command-line parameter expand to a
4 h+ n  Z, t  v; u
5 r) }9 z! f1 Z* {# separate word. The quotes around `$@' are essential!# i# X0 _; U0 v+ |; K

# x( q6 v! A( [/ p/ X' w8 p. b; X# We need TEMP as the `eval set --' would nuke the return value of getopt.
  X- ~6 d4 d& v  d+ B; y9 q9 o* ^
- Z1 v8 s7 {0 C* m$ {; ?2 O#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
! \/ t% c$ B& }& n* `4 X/ E) O4 q$ Q3 H5 g
#如-carg 而不能是-c arg
/ A/ U  V' z. t: d
: X, r- ?/ N/ A! s7 M0 R* K#--long表示长选项
0 m1 s1 H$ L) N7 ]" D$ b( z0 F$ u* _- O/ Y6 e) M' J, l8 j) J
#"$@"在上面解释过
* Z1 G" b$ o4 j% ^5 b' I( x, e# G2 O$ ^
# -n:出错时的信息
( g6 C8 {. B. n# C1 t$ X# k$ s! @. y+ W$ i7 W( h; B& l; d- i& i% k, f
# -- :举一个例子比较好理解:0 R. {+ P% W3 m5 _9 m
1 ]+ Z9 |' N( w4 b
#我们要创建一个名字为 "-f"的目录你会怎么办?1 a" t/ ?, |7 R/ B% w
4 W  i2 d8 w& D
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
( |8 y- W9 I$ S
' [( V& C( p, A/ V# mkdir -- -f 这样-f就不会被作为选项。
+ z7 I  K! S/ c: N, v3 V# F; F. _
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \$ ~* {& z$ U3 \- e- K; |- e7 O- A$ b
! N$ y: V6 s5 F
-n 'example.bash' -- "$@"`1 E' y  f$ @" x5 O/ t
4 Q% K) d/ {8 H2 t8 L
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
. T4 ~  u9 |/ f; Q2 l4 t6 A$ c; R/ o6 F# Note the quotes around `$TEMP': they are essential!
: r2 D( V: L! Q7 O& X6 }' H5 n$ Z1 D/ z0 v* r
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了1 B* F6 D7 b, x

, D! f4 [; ?1 w8 f5 K5 teval set -- "$TEMP"2 J+ f5 ~# P7 I3 N0 _
0 W( K8 I0 a, p" W7 d2 h
#经过getopt的处理,下面处理具体选项。
% c1 Z* q% Z. H, b4 |
) l  s0 y; r( P; m) Awhile true ; do) A  y+ I( V5 t; W* e, G

" U5 Z' _7 {$ p& [/ j* {$ n9 fcase "$1" in
& k) t. Q' l3 C8 g
. e7 V4 P8 q* N5 X( k: H  T-a|--a-long) echo "Option a" ; shift ;;, T2 [$ o+ z1 z# T+ a% O3 O
2 l, m( n6 L* i
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;8 m0 i4 A1 Z) B+ L" m( C  x8 I( B

* B7 ~1 X0 c" A, G0 X-c|--c-long)- l' L' y2 `* f$ t! U; o' _
  Q* w8 @% @' r
# c has an optional argument. As we are in quoted mode,
$ z) R- m3 t7 U: w* e4 j
7 w( `, {- F5 n( j" ~! \+ J# an empty parameter will be generated if its optional
, ?8 j  l0 S: \; k# E% x- U" x# b
# argument is not found.$ T" o8 J, p+ D  J/ ^$ e
" o  K/ v; d" k: N' y5 m
case "$2" in
/ E5 {: _# r+ p5 c9 }  n. K1 u: L4 i( G) [9 W9 r
"") echo "Option c, no argument"; shift 2 ;;5 r- m7 O0 ~  _, L6 k* r8 F" h
# }7 Z8 t) B( E7 o  v6 S0 H
*) echo "Option c, argument \`$2'" ; shift 2 ;;4 f( k8 b2 J7 z& J# a
  P/ G$ ~+ v0 f& \6 [2 E: b8 B
esac ;;
* V0 L5 {) s- n% R8 |4 I/ X# H$ H) w/ P5 e8 p% C* E
--) shift ; break ;;! H6 c8 U7 H" Z3 s, h* `* Z$ }  `! d4 h, H

* I: c: M- v0 k& R9 R# `) G. r*) echo "Internal error!" ; exit 1 ;;
. h: ?7 T) C) C8 [, A1 ?; B0 B, f/ J6 J" ^# ?( H' S
esac9 k" K/ Z3 n4 s! E( T8 B# h

& A! a6 v9 Q- x# c: C0 Hdone& I/ G7 U. v( r; i0 O
" s) ]! R2 t  O  ~6 r( o* x& ~+ O
echo "Remaining arguments:"
9 I4 l: i& A7 J/ A! g4 D/ S" ~8 K7 J
for arg do7 b5 Y" Q8 p3 v) B" d7 j
, S; }. t, W  p5 e) b4 |
echo '--> '"\`$arg'" ;
5 t9 X8 V, F: D* i3 H+ C$ J0 w. M8 M; Y, ]8 o: e; i7 J
done
; ^& T5 r$ y0 w9 u3 z' O
* _. i) U3 O6 N" {
+ m2 D( T  S* C) O) `4 G比如我们使用
9 d+ p6 g1 A0 I+ S% B* m) d6 Y9 l
% g% H$ q, K: M7 P' d./test -a -b arg arg1 -c
: |! X  d: ?) ]
0 ]/ a' O4 R+ d; s. P你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:. X0 f6 L5 c5 }& |& O
" t0 r- ~  y7 v  t0 z9 F
-a -b arg -c -- arg1
( W/ b+ A- R0 p3 Z5 F% E+ k, K: z* p- E. _" L, y. J2 C
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。" n. L: n+ q/ ~  W
5 [7 I: q. _9 C2 j/ K
3. 总结8 N% O/ x% Y! ~' _  f" n6 z
. r- c- g6 ~+ O
豹尾。/ X% E! x7 H% B+ K8 e! k
$ W/ D7 A* K: W' ]+ h! ]7 I
本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统7 ~( d) U5 D: n* q* X1 \

/ D' y' q+ v* H. i/ v" `* K
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33
6 W5 ?% e! ?* b7 i, _记得getopt常与shift结合使用,while循环一下就好了。
! i! P: }0 R, N! y4 V! _+ A
请教一个问题3 Q6 M6 W$ K* l" f; E
有一句 :set -- `getopt -q ab:c "$@"`
6 ^  J5 X: C' L请问 这个如何解呢??3 N8 M9 z* n8 F2 v
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句
* g5 f& q- Z* t& A$ q) `; Oset -- `getopt -q ab:c "$@"`1 s/ N# h$ [! O+ g2 w8 j' ^  j
while [ -n "$1" ]- w1 h- H) h6 \
do
0 Q& D" N( p" u/ O# N5 T/ s8 i  case "$1" in- v! {% o4 E/ L# g
  -a) echo "Fount the -a option";;* p1 i1 B3 c) }% W" k

; @3 s7 T' Z7 V& ]  -b) param="$2"
+ k+ f0 a1 P7 @& Y) X. R      echo "Found the -b option. with parameter value $param"
2 Y2 V* K1 q* v6 `$ N$ v      shift ;;
- i6 H! f- Q2 b2 `5 e4 P1 I! X" m$ X7 t3 K7 J1 E: z, `7 e# @
  -c) echo "Found the -c option";;
8 a) x6 x  R7 C7 A
* n" i* U7 l8 F+ B  --) shift
8 r( ^& Y! \- H% O8 T1 [! ~      break;;
- R1 \' H" z1 I, h4 i4 k: j2 z: g+ ?( c$ U# ], I$ g9 ^& b& T
  *) echo "$1 is not an option";;
' J$ o- ~! E& I  B  esac
' h8 h/ t' H9 u0 Z  shift$ K5 Q+ X" V* f% f, \
  done
. T6 K# E1 N7 u9 `# `& ^1 V0 { + @+ u1 \+ e$ R, n% y8 j
  count=1
  T) e4 E9 v' F; X, z  for param in "$@"7 m  l& I  M; V! t) l7 C
  do
" i' \& D) F# `1 {; v    echo "Parameter #$count: $param"
0 X) F" C6 ?% O    count=$[$count+1]
+ N0 E* \- o( [7 e$ }( [  done; k& R" Q" C* j/ M) z0 W& I
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39" t0 s  M& A. h6 x
请教一个问题3 {! |- v2 ]" f1 f" p3 W
有一句 :set -- `getopt -q ab:c "$@"`
* u3 E) D" B8 S8 x请问 这个如何解呢??

/ J) j: p+ d* G: R: g+ T0 O请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
9 M5 o$ U) ?  h1 o" k
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
3 \6 t/ T$ W8 U; W0 s$ g( c请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
- \; E1 ^  E; e4 W. t2 I
呵呵没关系,大家一起学习呗。6 }5 O% ~7 P, k- L, x2 l
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F
& f2 p- b7 b! w7 |一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,
' }9 o! m/ K7 ?1 T# x所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。1 `3 Z2 B! @: W( |) `% r3 g
如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--7 d; w* Y7 |* _- A. g0 z0 F( Q4 S
$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
1 l9 U% I6 k4 a% V5 j+ R/ n补上昨天调试的代码# M* {3 r9 k& ~- q

% B& T! w# P+ |1 V5 F8 R$ D#!/bin/bash. J0 F! U0 H" _
set --  `getopt -q ab:c "$@"`8 D! s) j  J! ^$ L# I, w
tt=`getopt -q ab:c "$@"`# m! A& i4 d  S4 T+ a
echo "\$tt:  $tt"
& k3 Z5 V6 r& `( k4 Z, Y# q- Oecho "\$0:   $0"
1 t6 \0 [- n, W. F% s& w- }echo "\$1:   $1"
7 Q- O( h: Q# @' w2 f! Hecho "\$2:   $2"# p8 Q3 x& M* t1 Y7 k) b
echo "\$3:   $3"/ ^, t( o5 l5 X- W
echo "\$4:   $4"1 j" M( U" X$ Y+ M( p  e
echo "\$5:   $5"
& x: D3 r! Q- L8 `, Z5 a/ D' _echo "\$6:   $6"6 Z1 s" _; B' ]  z2 `+ A0 P1 P2 K
echo "************"
7 v$ C& a9 K1 M9 K
# k; u) B2 X5 H- B
( i) v; f) F$ y8 b2 j
' O& D5 s* }  E: z* Rwhile [ -n "$1" ]+ r- q7 B8 ?1 x& b. d7 m+ ^8 i# d9 k' V
do
. v2 X- Q  D; @6 N) X6 \0 V  case "$1" in
: _% U3 g! j; i+ ]/ Q  D% W  -a) echo "Fount the -a option";;
1 B( F( v7 @/ r. q, |! Z1 M/ W( E/ i1 O; n* c* `
  -b) param="$2"( W, X8 v2 R5 p
      echo "Found the -b option. with parameter value $param"9 R, L5 e3 n- N/ n" j: ~+ ~* i5 o
      shift ;;4 [9 A5 ]4 _0 k- ]0 {* z; U

( b0 M9 s0 Q" X! @' c. Q  -c) echo "Found the -c option";;7 z/ R' k: K5 @# {9 m" }

1 B3 n- v9 j0 `; G1 E( R1 c7 U  --) shift
' w! Q" z, B% J      break;;( l! x& }: u7 _3 b* P4 ~  X
! T/ ]& D& x" O& J: T
  *) echo "$1 is not an option";;
6 e" f4 `; _  Q! _1 N6 ?  esac
. t4 S4 U4 G! o4 Z# }9 N: a  shift
! E) J0 {! b1 @7 ]7 W9 ~  done
+ i- a; d4 p" h2 i* S6 ?
1 \6 W8 M# H: v5 z2 i3 u0 n+ b  count=15 r( d& F; M4 y9 A+ ~; d
  for param in "$@"9 C3 h  _$ Y) P$ D- K! n& j
  do
9 a6 \4 G/ G9 T    echo "Parameter #$count: $param"
; W, e; s. B6 Z: j5 w0 |    count=$[$count+1]
- O! N: w5 j  k# ]  done
, T. t* T* s% P, j! d# z' }2 i, g* e' J: f4 C

: b: D: a) K7 ?4 {, G3 C% _4 L! l  d5 H$ q  y, \2 b
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test
: @: I/ x4 U" c6 {4 _; e$tt:   -a -c -b ''\''test'\''' --
* j' U" Q$ e. A6 f0 w$0:   ./getopt.sh
5 r; ?4 [0 a3 n& p6 v6 g$1:   -a
7 i4 O" ?  _! ~) Z, c% ]$2:   -c) ^9 D: X& {, a) u
$3:   -b0 S% D* @# ~) b% C$ I3 w
$4:   'test'0 _/ F9 [6 r  ~; ~$ Z# t4 ]* z
$5:   --/ l! Y8 ]3 b, z3 z. H
$6:   
+ A2 b9 B; ]* Y************! V7 S/ J( j: l0 U. g+ [2 X/ o
Fount the -a option2 N/ M! @- a' a: ^. r7 \
Found the -c option
/ y4 W7 W" {0 ^4 H- O/ }7 y4 fFound the -b option. with parameter value 'test'
' K* ~# m& n  Y! R
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法" @' D: j2 I3 Z) m( ~/ r7 ?5 U
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。! j% U( S9 i' h% g1 b6 |
代码:
% p+ B* Y0 u0 h/ Q. Gwhile getopts :ab:cd opt) }! b/ R  H" i/ ]
do' H; d4 L/ Y( H
   case "$opt" in
( i2 A. p. P6 ~1 v  a) echo "Found the -a option";;
2 O! E$ o& l9 t( f7 B  b) echo "Found the -b option. with value $OPTARG";;
/ q7 {4 x5 u2 x+ [  c) echo "Found the -c option.";;7 w" L, ]( u- S( a9 d3 }3 ^4 \# w
  d) echo "Found the -d option.";;2 K6 v9 R- _% a" a
  *) echo "Unkown option: $opt";;
5 Z& R' @& `  P7 g  esac
5 V: f. q# m* z+ E5 }: s* l) o+ `/ Bdone
' s: J* b+ }9 K7 b2 Wshift $[$OPTIND -1]: y; w  O- E0 c9 r# |2 e
6 s, {& y2 {+ ?- E% k
count=11 i( A: d( z$ ?- w
for param in "$@", ?- }5 z5 x: S8 E2 l& w2 Y& `0 a
do
! r2 |& K9 Z2 m   echo "Parameter $count: $param"
: O( [& Q5 j6 Z3 G! X1 E8 ?) R  count=$[$count+1]
) j9 |& ]- b7 u* l5 ]done
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。6 ^" K/ Q2 _) @1 q) ?5 ~- }+ ~
其后就可以这样用5 D# `9 \5 S. j3 V; ^- ^
./getopts.sh -a -b test1 -d test2 test3 test4" E' K; {! `( Y0 c' F
./getopts.sh -acd -b test
7 E# z5 g" P. }: d./getopts.sh -a -b test -c -d test1 test2 test3
  U0 R0 P5 N9 h等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash+ t# s( ]# j8 D5 Z6 L$ L8 r% u/ J
0 n. J9 ?  G: B/ D* a
# @% z' k( C! _7 U
while getopts :ab:cd opt6 D! J/ y4 C6 N8 c" M1 E
do
+ r& c( ]6 y7 ?. r) T% l% f  case "$opt" in
; _2 v' S+ [$ g! |( L  a)echo "Found the -a option";;
* ?( s/ T, R6 U  b)echo "Found the -b option. with value $OPTARG";;% b1 ^. T9 x+ ~1 a7 h  Y
  c)echo "Found the -c option";;! A- l' {& a" ^" ^! o6 H
  d)echo "Found the -d option";;/ U& e: w2 K7 N
  *)echo "Unkow option: $opt";;
; L( p' H9 [: r! x/ `( A7 v( [7 z; K; d  esac
% X( R9 V. Q, I2 J0 Udone  g; O+ v- B4 c/ o0 P' N  q
# Q- v0 D, i; `6 ~& [
echo "**************"6 I: y7 C0 d* q" p" _$ A. h- {
echo "OPTIND: $OPTIND"
4 a# U. ]$ L" l  X" J- Z echo "\$@ $@"8 u7 Z  K- e/ F
shift $[$OPTIND - 1]: y7 f0 S' u! T1 Q9 T2 {4 @
echo \$@: $@
0 L, B1 I2 H; M: [" C) w7 p  D" J9 z& B' V echo "**************"
8 c( w- L' j. l% Z: z& t
1 H+ a! u3 y0 T! }count=1- l9 e+ ~! ^  Z8 s* ^) J! |
for param  in "$@"
  P* T0 Z+ A/ i! O  h) A2 wdo
+ F# [5 z4 @1 b; _5 b* m  echo "Parameter $count: $param"" @7 a" P. j1 k* h" Q
  count=$[$count+1]
8 F9 O+ l' P  J5 ^' ?done ) x. H& [) R# g2 G" k  I9 r8 q8 j
! V1 S% p7 V! R' ?4 T1 p
6 |  d/ n1 Z3 k' X# v$ M

6 O6 O% R) ?( W. V# b  c其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过  U0 I2 z4 t8 \; Z, o
7 J; V- t! T) a7 X/ R
回复

使用道具 举报

本版积分规则

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

GMT+8, 2026-7-13 06:37 , Processed in 0.033483 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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