一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 4161|回复: 9

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

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

! A: @! D+ d0 F+ j& G$ r1 @getopt/getopts:Bash中命令行选项/参数处理
# h% @- ]6 J, Q8 b) T  {+ j
& @  D. x* a1 q/ y, a7 T0.引言) e0 u; v1 A# s( t

0 N  D' W  F  a, H- z写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。7 V/ M3 f7 G  a6 D8 ?0 T
4 c8 c, t  U2 Q
选项与参数:+ T7 \# \3 o! _( g: I$ v+ a2 l
4 z! l' E+ r7 x& W
如下一个命令行:
+ E  Q) \8 ~: i8 c8 |2 z: |7 O# J- R$ m
[vb]
: l4 V7 p% ^9 @: D) D9 y./test.sh -f config.conf -v --prefix=/home4 I% R8 m& d  ]
' j" t7 M8 B: _! {6 _3 R3 @
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。* G+ @" ^# H6 c4 |7 P
( \+ K% U1 w7 q( W! r$ [6 I3 a
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
8 s% k& o7 S. S0 w6 Y- Z+ R; s( ~' x* \( H: v8 q2 ~
在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
$ q7 u% Z/ ~$ d) k: S1 `. ^- W8 c$ j; K: U% ~2 r4 o8 j
手工处理方式
! q6 ?% Z0 s# a
) ]% I: t* f( v, o" [getopts; J( u( ~  K- m) k) b
  L, E8 _/ \1 R  o
getopt3 L6 ]8 d* U0 {: e! Q: i) k' c+ L
- P# E3 C) T8 H9 j1 o) B4 l
下面我们依次讨论这三种处理方式。/ G0 Y- e! y* e% D& b

2 \0 L9 `2 Q4 i9 y7 O4 w' z1. 手工处理方式# X5 r+ @7 n$ \9 a

& v4 x+ J* L1 k, a* e) |; B4 ^* f在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:; o% {1 U/ o  Z; a' r
/ f4 g* m3 k! X. g9 D: W+ T2 X
$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
1 q1 |" y% n* _4 E. q- u$1 : -f,第一个参数.. x9 q. @4 T# {
- m& }6 Y' P( {5 L- r) Y! ]- w
$2 : config.conf. o! }: ~% p( p# y% E: k! u

. W$ Z. _$ T. [6 X3 i6 B7 R$3, $4 ... :类推。* X0 R2 Z" U# e4 O; {

& U8 p5 O4 `- w  g% G6 U$# 参数的个数,不包括命令本身,上例中$#为4.% f! G' ]+ I9 A% q3 W$ o3 N
. a$ A# U: D& a, C
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
5 m  R# _8 ^  I7 z; U( f4 A2 b8 {- i8 B! z* q: D* ]0 `
$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:
6 y4 w% U3 _+ m( w' h
1 W0 t4 [& M5 M, y[vb]
- B( ~& ~5 n, b1 y8 c2 G% P3 I#!/bin/bash
1 _+ \4 t0 X' h2 m( p- I6 J$ v, r  @
for arg in "$*"2 Z& g% ~6 f, W& c

# W& V, _  p. A4 r/ x0 ydo! X, G: w# _* ]8 Y; C$ B# U

( {* x8 D  g8 U9 Y  c0 a4 l$ b4 aecho $arg
% X. i, b$ p% w. q0 a$ g
$ i8 z1 T. }& I/ J0 m! Zdone
2 l1 G9 }; H: E. z' B' J2 D6 n8 u# k- @  |4 Q) {1 N
for arg in "$@"
% b+ i. q/ i0 Q$ Z
- c( V3 Q: H3 W# |4 m7 U; Jdo9 h/ R' R: v- B! m5 o( g0 X
6 y5 l% x2 p) }% u! l* a& a
echo $arg
& e$ @5 Z# E5 T! I8 Y4 j1 u4 ^! W5 l* _# i  _3 t
done4 J# P5 c# Z5 T
- ~4 j9 g2 N; p
执行./test.sh -f config.conf -n 10 会打印:
9 u( J$ x+ A8 N- A( t& H7 p! j5 o7 W( r( T, V3 l6 o, |- w
-f config.conf -n 10 #这是"$*"的输出
2 U  x' t3 d* i: t8 ]( z7 a
. v# R9 T  `! r! N, p( g8 T#以下为$@的输出
) ~: J  @4 G- U, A0 j. E
6 s# r5 w' M" `  j1 X1 r* H-f
0 W5 n' |8 O% ?# M
/ a) Q( ~9 K  Q6 |4 |% |" N! {config.conf' z* f5 @% X7 t+ Y1 D) `( B: u

' F. Q$ s; t  a% w-n0 \# U7 z, ?0 ]# d! V8 L6 k7 Z

  l! E/ ?0 Z- m9 O104 B7 \- I8 f$ K  D+ J

4 a! X: X1 n; r8 L$ [所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
' R6 i) a8 {# q+ i
) Y( Z4 G9 p2 R  A# A/ D6 b* H9 G3 K“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:# R0 Y* M( u% Q% K7 M& ?
' t# `1 Q+ }3 L* r) K3 `4 Z
[vb]
2 ?$ J' v" `6 _6 p; y" \/ [#!/bin/bash
$ E" k0 o3 U+ P! K' D. S/ k- d
7 Z5 D/ T8 v9 p, u4 C#if [ -n "$1" ],参数不为空 5 }" c- c2 X+ k/ H: C
if [ "$1" != "" ]
- r6 a4 ^: ~. v1 ?& ^/ pthen
( o) Q. a2 `# l) r& l- a$ g8 W' o+ S( v
#...有参数
7 @4 z( h' G9 v8 m1 E; d6 I: G8 P/ c5 o, h! j5 d
else$ w5 \0 @7 L- a' @% {* r. H

7 B' v  r2 x# T3 ?' n3 Z9 vthen& ~7 K" T  |) W9 g) s) B( D& \
' U" H7 N4 {9 ^
#...没有参数& Z6 I7 ~4 C' e
/ t, A: Z% @! G8 E. u; Q/ j
fi6 w0 T- o4 c8 I

; h! u& o9 a/ Z, C: W手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。- z( @' T) J6 n, c% S; \

' {$ ]: ?( h8 L! v2. getopts/getopt
# @! l4 w4 M. \3 N; Z2 c4 ^7 h% W4 ^1 F1 E; z) C5 L
处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:0 [  p. b9 {- ]6 e% X0 v/ {
. o. s* G8 P9 J" N$ r
./test.sh -a -b -c : 短选项,各选项不需参数
6 {( I! J( K# B1 J6 x8 H0 R' o
3 X9 T1 N, P1 s+ h3 i./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
% b3 M9 I' y$ P8 t" I: _
# ^6 E$ O' d& {* ]* e! ?) Z./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
% J. P9 w9 W& I8 W4 `/ u9 Y. ]' ~
6 R/ p! Q; D6 {7 f6 O" I) O  S6 @./test.sh --a-long=args --b-long :长选项" F/ g4 f- \% i6 C% J6 m8 f( Z! h9 K
$ E: Q! S( o3 c3 w5 G" `
我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh* H% l8 _; S( e  R

* O' c3 a4 G* k. P) ~' x[vb], _, T$ C: P. J' Q7 C! X6 e
#!/bin/bash) ]4 R* j$ ]4 P$ F

9 h- }6 B5 }: g- g#选项后面的冒号表示该选项需要参数( m- A2 ?3 n- n, z1 A# \# L4 S
" Y/ }% `- \/ o7 Q- ^" R- T
while getopts "a:bc" arg9 ]  @5 A. S2 I% E3 j
2 q2 M0 D1 k: v( }/ \% e4 w
do0 @/ x5 ~' a2 y( ^" X4 R

, H- b: l; s  {case $arg in
' x6 P1 {3 Q  U8 P# S/ A  x6 b  V( V  f9 O$ _
a)
( \$ B: ?5 i/ j. Z
: D' V4 J% B  {+ K$ f#参数存在$OPTARG中! s$ ~) p4 k$ H/ k1 e# z- Q$ T" y

0 p, D2 j. `& {/ v+ h; b) aecho "a's arg:$OPTARG" ;;
2 S- c# \' S. |- I( X2 I% W3 q3 {$ W6 E. P* C/ x
b)% q4 q8 B8 t! `) q
6 Z: B( S5 ]  I; W3 F4 d, j& A; E3 u
echo "b" ;;
# _: O" q* t0 F3 w
  u; ~/ H' l* M8 ^; [1 Tc)
0 K0 p- a# f+ i. s% O3 U" i
. ]- C, R3 E$ T) s  x! Cecho "c" ;;
/ ^; c% U, ^. [" u/ {2 B/ `! F1 R- K) K1 g3 D; V; V; Q
?), \! N; A5 T8 X+ P" o
! a  d: U% x: b7 {& O
#当有不认识的选项的时候arg为?2 _/ b0 q; s  _+ E' ^1 U& u
" c4 s$ b% U8 n
echo "unkonw argument" exit 1 ;;
8 z  m0 o) K' J; R* H0 [- S9 h! m( r" Y6 I; K- E' ^) s
esac; H/ _0 g, B4 P0 M7 q

* f& Q9 V& P4 k" p) kdone$ G  g) \* o$ }$ i  ]
* O& ^# C& p) ~1 s0 B& g  x
现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
: G. Z. _, w4 e$ q; V( M8 Q
) G+ T+ ^* v" u  [来加载了。6 Z) L" I/ c  n: c0 g% }6 ^

8 _9 L" G) p' y/ s应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
* R1 g! f- Y- K: m, l: ]# R- \5 k
[vb]1 G0 t. L$ m  |5 P/ R
#!/bin/bash1 R" d+ E* l$ x
6 s: |4 r* ]# Q( j' e( B
# A small example program for using the new getopt(1) program.. F) Y" R4 m% {" E  X, K
, E" ~' _9 o4 G  C: T! r
# This program will only work with bash(1)0 r; ^; |* [: Z! e3 S
" C6 P# J* J  \
# An similar program using the tcsh(1) script language can be found- D/ U% p  B, \" ]( f3 b+ O( b

# e6 M, k) j7 H9 X# as parse.tcsh
8 J+ @  U6 r' _4 j2 t. C/ v9 \& j) D- J& g
# Example input and output (from the bash prompt):" `: v% T9 X; ]

/ K! ]  k0 b! ^1 `: |, `0 T# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "; j# H3 e; G- j* b% i6 I- @

7 Y/ S* e# _1 D7 d# Option a
0 l& @. O) x* |# t, _% S* C, f) x, s9 g2 E
# Option c, no argument
2 ?) A! \2 U3 Z- V, A! l
+ ]9 l) X: @& {: s" y# Option c, argument `more'- H  K: m' V, T" t+ I( m
2 T' Q: U. }+ z4 X( W& x. j
# Option b, argument ` very long '
9 b4 i- x& E( ]  H+ q' p  n& P' c/ o6 G- X6 F1 E' k) M1 T
# Remaining arguments:
8 X6 A$ W: K1 F. b6 w
) r2 X3 _. S4 Z! i5 u5 E* p# --> `par1'- p" w8 q3 _. O4 D/ p$ R/ t2 T
" l0 o+ w# ~% T5 O5 k  l
# --> `another arg'2 c4 C" p2 v; \$ t) o( `$ s7 g

$ I2 \; E; a; m' K* l7 g# --> `wow!*\?'
/ w$ b, ~0 p! W( o% Y- b+ h: R: Y  L$ j
# Note that we use `"$@"' to let each command-line parameter expand to a  G% a! k6 K( V- l% G
# _0 w, K( C: h1 d, r0 {/ G$ e
# separate word. The quotes around `$@' are essential!% ^" @" R. R# q( i: {) b6 S2 ~7 R/ [* ~; n
; ?, H$ P$ [7 y- S( h) i
# We need TEMP as the `eval set --' would nuke the return value of getopt.
' T1 I( g% f: v
7 t2 K( H% Q: e9 p* N& |3 r  [#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
& h* B; o) f% H: w1 M1 S# |( T% g
#如-carg 而不能是-c arg
: M$ G  O& v( ~& R* @2 ]! W" P8 Y5 y8 z1 i3 Y  k$ c: X" p' @5 S: M
#--long表示长选项
& _( Z# _+ ^% t6 l* A
3 _$ n4 w+ {' A5 h2 o* e#"$@"在上面解释过7 V7 ?3 R  _3 }2 Y* {+ {
& ?! M5 c* e& W( e( \
# -n:出错时的信息
# p# i& a% T8 R  w( X5 O' l2 ~$ N- ?, a( B
# -- :举一个例子比较好理解:- e' M3 o# s9 \  Z' R  q" u- X

' N4 j2 u+ c% {# c5 O& |5 P#我们要创建一个名字为 "-f"的目录你会怎么办?
8 h3 J, k  y( z' z2 V. I+ F+ ^. L' l
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用" D' g- z/ I' k4 j& L

. n  }* ]5 Q7 D  U  h# mkdir -- -f 这样-f就不会被作为选项。
* e9 c, ~+ G7 E+ g* z9 [7 G, l+ t/ Y: U% B, L
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
: x! C+ R- C2 w5 q+ |/ s& M
2 I- G0 \/ E3 b* A& B+ @-n 'example.bash' -- "$@"`
0 \( @5 \! S! |+ V6 k# F) r3 z; K3 C
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
% u% q* |6 q; S+ y# Note the quotes around `$TEMP': they are essential!& ]( y! k# R( i% h9 r) t+ u
* j' y# g* _0 M$ n# I+ y
#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了$ |# J+ f5 J$ l# o5 S% f
9 j4 Y# Z  {6 L6 o' v' W4 Q
eval set -- "$TEMP"/ e( m# u( I+ @, a( t" e* g; _

0 p; [/ q# \1 E! S& D$ a) J#经过getopt的处理,下面处理具体选项。
1 q. H0 T+ f1 y& `7 O
8 w; t/ K0 E# V8 c, }6 Owhile true ; do/ P- c7 I+ Z$ v* w' {
2 M7 v, c. g: w& j) `
case "$1" in
$ m- g, D# o8 x3 p
; |0 \$ f" ^% M* d: J  A# {- L. N-a|--a-long) echo "Option a" ; shift ;;3 D4 ]9 Z) U' B1 Y5 y6 m
* \2 J3 g  }4 v" p8 e8 C" L
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
  I  i6 t% i5 ~; v
; v. W& o6 s( {-c|--c-long)1 R4 U) r  z, e9 ?4 v  {# ]. I
1 p( ?1 H* S2 C1 ?! `8 L$ j
# c has an optional argument. As we are in quoted mode,* Q. e: ]) B. q. F: T0 _$ q, S9 J
/ i* _2 z" b; m$ v
# an empty parameter will be generated if its optional; B3 o1 r3 I* [/ ~1 L/ B

1 A! q* _8 `$ ~/ \5 l, _: I# argument is not found.& u  j/ F% ]) a- e# x! R

- O1 f6 E4 p5 S3 c3 H+ bcase "$2" in
! u, u) J5 ^# J0 S' S+ T- x7 P, i' b( e: L
"") echo "Option c, no argument"; shift 2 ;;0 o' }% j' F6 V' `* f3 k

2 f7 c7 ?- S( S1 G$ Z*) echo "Option c, argument \`$2'" ; shift 2 ;;
" A6 a& a3 |+ s" `9 d7 e7 H
# A+ Z% _' r. e3 {esac ;;# Q9 ^; k' v: u5 v( z' T0 T
! T* m5 }. p& Q$ `& b
--) shift ; break ;;
1 s: d5 a( A# A6 ^: T8 y# g
6 A1 p' ^+ K2 |( a9 b# U*) echo "Internal error!" ; exit 1 ;;1 L8 F9 C& v& p' O0 E0 E' ?9 M" N; F

9 O+ g: h- F! @( `esac. ~5 G/ _# l* v1 w* {  I5 N
$ n, F* c0 R) L- Q7 F
done7 {2 v+ Y% L+ a% r; ~
1 K3 V' \5 c* U7 c3 y
echo "Remaining arguments:"
/ V* g" ~) m6 y$ q0 y
1 I( i' ^5 w" f2 Z% C/ s, E& _for arg do
/ U, I6 ~1 u! u0 o: D1 O4 l( _
echo '--> '"\`$arg'" ;
# K# u3 x/ o# Q1 J6 A
( {5 W+ Z8 M/ J1 Edone( z# W2 Y* i$ }+ ^( l
0 s+ E8 H& W6 n. v! P8 G  r9 D

+ o# ]" }7 Q5 J0 n, ]比如我们使用
4 G& V$ m( M8 I5 Q% T- m# [3 ^3 M
" _  b2 c3 V6 c./test -a -b arg arg1 -c
+ Q7 e8 V7 W& L  [5 E
! h) q9 @9 n  v+ H9 P你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
( G7 c5 v1 n# Q( {' U/ m! Z$ e) J- g" ^8 R0 J
-a -b arg -c -- arg1
! ~% q( {. u. q$ z# M/ H. P! z3 l% d# s/ D+ `& n- g
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。# B. f9 e9 ^! P% F% J( T7 I, A) i
5 z6 V; g3 d% v! V# E3 q: T
3. 总结
3 J  L/ _9 D# ?8 N
3 E! f9 L" F6 y; V8 B6 q7 g豹尾。
, J8 w) K3 N7 j0 G" F
) d' {0 J. `; A( i+ s& Z本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
' ^9 Y* j6 `; t' v0 }- J( n1 t( k; S1 ^- u3 R3 m
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:33, v, a. y) G# n! M* |$ J/ }% I  ~
记得getopt常与shift结合使用,while循环一下就好了。
1 h/ d) b# ~$ [6 J; G
请教一个问题1 J8 S, {3 z) q5 x5 ?; K
有一句 :set -- `getopt -q ab:c "$@"`
7 ]2 z7 F; v0 }请问 这个如何解呢??
( b! @; {4 t2 f9 v: ^+ ?
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句
3 U2 |5 {( P, O; [3 |. n" rset -- `getopt -q ab:c "$@"`1 r+ x8 ^( w" y0 R1 M! Q% a
while [ -n "$1" ], M  C* `% O* l" W
do
0 `6 N/ x/ C3 E+ z  case "$1" in
4 r5 r6 P. g% |  -a) echo "Fount the -a option";;
! p. H( A6 _7 m7 E, C9 t- j; v/ l$ ^$ L' s2 O3 |
  -b) param="$2"1 C3 x$ }0 B' l+ K
      echo "Found the -b option. with parameter value $param"( v: I# Q2 C7 U$ V! Q" m4 a
      shift ;;
$ q* N" J# ]/ [! c, B8 r
# \) C4 x7 E, k8 Q- k3 V8 F  -c) echo "Found the -c option";;# d7 @" T- y1 R* j, s0 O. J
, ?# T7 J# A: K0 h! _0 N8 W
  --) shift
( V2 x" R3 b% |: K$ E      break;;
# P; r6 ]& P. F: `* Z" H4 D6 e2 s9 x  i( I* W
  *) echo "$1 is not an option";;
: n: b/ |, ^; E6 a9 G  esac9 c7 ~0 x5 [9 D% u6 D& x; w& l" d* H
  shift: M- d4 D, d( S# `" u
  done- j, ^) D$ f. x5 c; |$ x- w: w
4 _# J0 }2 f! W4 \4 d) B. e
  count=1
, c! D! A- z+ M  H- B2 {  for param in "$@": N1 i& p  ^2 r1 L, V8 e# `
  do- o& ^) ?# H2 I3 E
    echo "Parameter #$count: $param"
; Z- a1 L" p' B& j4 d4 @    count=$[$count+1]
7 _0 t4 ]4 q: Z  done( F' v2 M1 o/ `* [
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39$ E) X. e9 X- X' M
请教一个问题% E; u' L, q: L; ~/ I# i; M. z
有一句 :set -- `getopt -q ab:c "$@"`
" ^" k0 M3 [2 g; |请问 这个如何解呢??
! Y) ~: @, O- s6 E5 h) A
请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
' [1 s* j. }' ]: K, Q' R$ O( j* X
回复

使用道具 举报

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

% \% d  p/ ^6 u$ [' f呵呵没关系,大家一起学习呗。7 B5 r, c- P+ g) t$ W$ h
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F- i% W% f; J# o0 z! ?2 v7 m
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的,
1 L+ h& B2 @  g, Z/ a  z& R1 D所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
  p  S9 u/ ?9 b+ b# l* r, h- _; y  z如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--
7 h5 y6 N7 o3 Q$ R$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。+ N; G+ r- U" X6 O' Z
补上昨天调试的代码" P' t4 ?; h/ i$ d- w! p" }9 ~

( U8 M% c' n& `5 S$ X) j: u  F#!/bin/bash
: {9 l( k  C2 Y. N& Mset --  `getopt -q ab:c "$@"`7 `. k( x9 j" t" H1 F" e: G
tt=`getopt -q ab:c "$@"`% Y# Z% Q" j6 @$ @+ B6 {
echo "\$tt:  $tt"0 z2 k2 V5 Q. u: l* R, N0 X4 y
echo "\$0:   $0"5 K' W9 y" d  t/ j  J
echo "\$1:   $1"  b* X# S) v) n6 I+ _/ N
echo "\$2:   $2"
! n+ E* U" y( y/ G. S3 hecho "\$3:   $3"* ?7 n4 U! }' P  @3 F. b
echo "\$4:   $4"
  Q5 S1 `, M( H- q9 W( Hecho "\$5:   $5"2 i3 K% B: z3 G: O" [& S$ w
echo "\$6:   $6": L- p, P; A  }1 [# j) u
echo "************"
1 L$ r5 k  S* G' U* @! q3 ^  I$ e6 P' r0 X0 g# i2 C

! e7 X- r* F8 J1 z, u8 \8 _6 r5 y# ~1 Q( V* [0 Z1 V
while [ -n "$1" ]
2 D6 x7 W3 K7 `. {6 ldo
- n) y* O6 o" ]  case "$1" in
: Y3 j9 }5 l+ Q8 t( `5 ^6 q  -a) echo "Fount the -a option";;
  E6 k/ M, [# z& D+ a
& l6 j% j: C: F" ?& p  -b) param="$2"
2 O1 D2 N9 @6 J3 B% D: T4 X      echo "Found the -b option. with parameter value $param". R5 [7 [* P5 t* g3 z
      shift ;;7 U/ C5 w( R8 j0 p

7 ~' n& Y% |0 c" a) o  -c) echo "Found the -c option";;2 Q, `  [* z; w" i4 Y6 @/ t3 W
% E/ j; C( K$ p5 j; s& i( u
  --) shift' v  g; C7 q  s+ _* c
      break;;
' u' u6 y- R5 o9 m5 h' m
0 a7 f2 `9 n8 O' N( j  *) echo "$1 is not an option";;
5 {# u- N. P& i$ G  esac- D+ P' k, g5 G9 ?3 z, ?
  shift
) K& O# M) X" `- [. |  done
4 m6 h$ D2 h4 k
( P' g; H3 e5 u2 `+ W7 A, j  count=1
. s5 m) R+ R& O) S9 @- B# C" t  [% y  for param in "$@"8 H! D5 V2 b/ t. d8 M4 U
  do; V$ ~+ Q( |! _! k+ y
    echo "Parameter #$count: $param"7 D' Q8 j# F' h! l
    count=$[$count+1]
; U7 \+ t, r( f" k& o  done
5 ^4 n' U: Y& `7 @  n/ X" z' d( j2 x
" y+ }7 l: D4 F, b6 ~, T6 Y, R' Z; f6 J

, t! N* k5 p% i) v, B
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test
; k2 N1 P9 |, `. u$tt:   -a -c -b ''\''test'\''' --# p, n' Q2 ]; o: @4 @
$0:   ./getopt.sh1 a2 }! m2 ]0 l: h7 q! {
$1:   -a0 v3 s- j6 i! M4 J- ^; S1 c
$2:   -c
$ f6 P5 i: X/ K" G9 `0 @$3:   -b
( J" i% N& f7 V9 s$4:   'test'( @9 \8 Z: H, b( j9 J
$5:   --
* r* U# ^. D: J; V9 h" l+ Z$6:   # e) |+ {, R  s/ b9 E7 I1 \- f8 l- i
************
8 x; s* E" C0 r; p" n( QFount the -a option; v) k0 w  Q$ ]' W
Found the -c option
1 O: p& R, F) W" `Found the -b option. with parameter value 'test'
3 Z1 y" z1 }# R
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法% A- l$ J8 j. V2 D# h
getopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
/ w) j2 {( N$ Q7 A( @$ @& h* U代码:
) j' X! Z& ~' A6 G9 j/ Nwhile getopts :ab:cd opt$ o( H! E/ J! C! S) T& v* `
do
+ F2 I! b  |9 L   case "$opt" in; C1 b; a) w8 ~# Q
  a) echo "Found the -a option";;- H6 d: d" \6 C9 `6 ^' [, [
  b) echo "Found the -b option. with value $OPTARG";;
$ n- k. C5 O& N9 T" }/ V9 c5 D0 N  c) echo "Found the -c option.";;
. ^( o7 C! }: ]% [. \" B8 L* W  d) echo "Found the -d option.";;
/ j/ G9 q3 D) b8 b4 h  *) echo "Unkown option: $opt";;
5 C3 r- l% A+ W  esac
* n) I. z* I! g# _8 n/ `% X  {done! h. G. H: E* G* G
shift $[$OPTIND -1]6 n. ~0 w/ H4 }4 k$ i' g
8 U& S) }' p- U4 N
count=1
, J6 ^2 _0 f; X% P+ o' v( cfor param in "$@". ?% J8 W2 X/ L) T" [4 i
do# V: k; u6 j3 `
   echo "Parameter $count: $param"
* x4 x& k% U& y1 `. T# @  count=$[$count+1]  E% y8 t- n6 K8 f6 [
done
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。
, o8 O% M2 W, z  X" G3 J  G. T/ W其后就可以这样用7 p9 d) W: [1 Q* W4 ?: i1 @
./getopts.sh -a -b test1 -d test2 test3 test40 v) Y% D% @1 M  R; v3 C
./getopts.sh -acd -b test0 B1 c7 V& U: v, ~1 |
./getopts.sh -a -b test -c -d test1 test2 test3 ' o0 B3 ?* ^# F; R4 T% h
等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash
  s2 ~. i4 n% a$ G9 ?% p. }
2 |) C  j3 {+ B7 s' T$ [8 }% i5 N& Y4 n4 d9 Y2 ^6 d
while getopts :ab:cd opt
8 m/ B2 [/ J. U9 d1 ido( V$ K' _2 u8 g( I
  case "$opt" in
$ d- B7 I/ W* }5 S4 e3 f5 u  a)echo "Found the -a option";;
0 ^+ `6 x% _0 z' t7 b$ w6 B  b)echo "Found the -b option. with value $OPTARG";;0 P/ z3 z4 {4 H5 D3 X; Q
  c)echo "Found the -c option";;; X0 O5 @7 j9 @0 b
  d)echo "Found the -d option";;! w1 B" H/ p1 S
  *)echo "Unkow option: $opt";;
+ R# H1 ~7 d# _8 r# ^; p% |; L  esac( i" w0 |3 J$ b% F
done
: S# R# z5 N# P4 x9 ~
. y' b2 k# Q& g( [5 |; I  t0 t6 e/ J echo "**************"
: ~+ R, ^9 s# p; j echo "OPTIND: $OPTIND"
4 |3 l/ c! t' T' _8 H/ O7 @ echo "\$@ $@"
7 O1 C% e! L$ b7 v shift $[$OPTIND - 1]- l# n8 @3 n4 h2 N( j! i1 x" i
echo \$@: $@8 A6 {4 }: a! k; ?+ J* J5 H
echo "**************"' e" U  q) s4 |4 C( h# g

/ N/ P/ L. d( A! h1 O! Ccount=1
% S( U8 D9 `5 h' d2 w- cfor param  in "$@"9 _4 k5 B+ n! Y2 L: M
do
! U% `3 s9 ^. Y7 Y) R+ p" g  echo "Parameter $count: $param"6 }: k. {8 N$ ^
  count=$[$count+1]
2 D" |9 o/ y* ]: D$ X; Z8 f, {done
6 \3 p# s# g5 Y+ f
6 G& m" D# B" X6 z: g( \6 t) ~
. C2 b& y( R1 i& F+ }" ?: g1 Q) Y/ K( D! {
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过
# ~+ q8 Z9 X% D9 y' L( n
! E, a! Y4 v; O( [' ^- ~
回复

使用道具 举报

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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