一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4411|回复: 9

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

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

3 [# H: r* f+ U. `( agetopt/getopts:Bash中命令行选项/参数处理$ U' Q5 V0 w2 n6 w6 t4 ?: ]) e

+ L8 F4 h. T2 A2 V7 x, Z0.引言+ o' H7 c% J: |2 W1 G4 X* w

" `( r' o4 e! h5 S1 k( Z, L写程序的时候经常要处理命令行参数,本文描述在Bash下的命令行处理方式。
) x" c( `7 ~" `! w6 w7 M/ _
% d( Y1 a$ S5 Q% w/ V) d* u' j选项与参数:
9 m# M0 j1 a* l" I# B3 W' A" ^
$ q$ n9 c/ J* B2 y2 J如下一个命令行:2 _1 A# s+ ~8 @  U
3 _" B: s- x" P. }, y7 x5 J1 q! r& w" m
[vb]- l, ?% x# E' e$ ^9 l
./test.sh -f config.conf -v --prefix=/home$ a/ ^8 D0 u1 z) P! n
3 T9 F- o) e& C5 h0 T9 Z0 f3 j
我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
4 R( d! ?  _, j" v
, w- ^6 G- b* Q--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
, F3 Y# O, h. b' R
% s9 _0 L1 e/ `" E  W' e6 F在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
5 a2 I( H' [+ x6 ]/ h& `' u8 H# E$ D" O- H5 P: `
手工处理方式8 C6 }4 i1 x! v& S
7 O" O& b+ r5 w
getopts
+ O+ ^. p8 B: n" f/ A
4 `& ^5 Y: O8 U8 y: ?& Ogetopt) j3 o2 U3 ]- d! B# P0 g
: V" N& A- k5 o$ [, `% n
下面我们依次讨论这三种处理方式。
8 z& E$ U, b+ h; S* {4 O. [6 w( \! L  ?& R2 m# B
1. 手工处理方式
% W& Y. Q! _9 ]" E! z" Z9 c" s- {; u+ D0 H5 R4 X- {
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:! f: ~& b3 C4 C6 H
! S, O5 H  c: M/ v2 C; ]
$0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]
; d4 `  p. [+ ^% Q- K3 X  F1 Q$1 : -f,第一个参数.1 U2 `1 b4 K- N# Y  I

; }& _6 _7 q4 Q9 b$2 : config.conf: W5 _3 k9 u- O" G
! @  F! t& F9 f0 ?3 Y! S# y! S& p
$3, $4 ... :类推。* Q+ h1 P! ~6 X3 F6 s
% C- p) K" u$ h# w* M
$# 参数的个数,不包括命令本身,上例中$#为4.
$ }5 {" o" T, L: v  T% l8 l- @+ ]; N: Y
$@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home8 _; Y1 ]* P. w, |1 a, }
4 d  K: s* N8 J, v. _& U5 u4 V2 Q
$* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:( A/ W4 l! W1 w) Q6 E6 M: l6 o# H
3 T0 K$ [% p+ i$ \4 ^6 G+ L- @
[vb]
( }" s# v/ J& Z4 S/ i2 R6 B  u: T#!/bin/bash
  i! _1 J' p! Y: f% K  D/ t6 ^
; v+ h; ?6 |7 y6 Q7 zfor arg in "$*"" P" J$ J* z6 t% D# F6 Z
! T, _5 l# z- r7 R" m
do; b4 b, y$ n* H% ^( E4 b
1 [8 K1 a0 k0 i+ R% y* E
echo $arg6 \( H" f3 i- M* B8 }+ I
/ ~8 g" C, {# U3 ^
done
* E8 N2 x; w3 i1 e! U; L2 s( j' n0 r, j! W
for arg in "$@"' s$ ^& p6 R. Q; b/ r

. e1 f/ ]0 K6 U, ado
9 q8 [. G% o' x
& |- g) l6 B" ]; {. jecho $arg
$ e! C" F1 W4 O3 s7 F8 w+ X( ?. v0 m) \& S& \
done
- ?3 O3 A4 U) Y6 d- _2 g5 Y
; x3 F! [4 s$ H6 T, {% t执行./test.sh -f config.conf -n 10 会打印:% k1 m" X4 _5 I! l; ^3 P) _
  q0 Z; r4 m- b4 Y6 c, P: o
-f config.conf -n 10 #这是"$*"的输出
0 u3 \3 M. M9 U
) ~4 X" v6 Q* s! Q$ [#以下为$@的输出" C* M( o+ f& [! X- Y

5 x* w3 \4 D4 {$ L6 S. W  V; H2 z-f
0 Q- f# c0 A, c% L# V; [. W$ a
config.conf
: q; R1 }/ @. N; {, C$ p
$ P" o* W# d9 w" n" g-n( V$ y$ c/ X* ?

& O( u$ s0 t+ f$ R( V10
, a" b, m6 U, D- T; P# f
, |0 M1 n: v. {# w所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如
* r% d) A" L: {+ }" J- `
+ H; ~. W) g" i1 K6 Q“./test.sh 10”,而很少使用“./test -n 10”这种带选项的方式。 典型用法为:
! n/ ]$ E/ X  u% ?8 q8 ^$ @& a) m
* H7 j6 J9 g% L2 R5 o[vb]
3 B) p9 A! h9 i- s#!/bin/bash! c5 g7 Q* n, M) y; s

4 K& `: n" B3 O: f3 ?$ z. A9 ^#if [ -n "$1" ],参数不为空 : r$ b2 a% [' K+ {8 B: ^3 G8 G% t
if [ "$1" != "" ] , x. r# l8 w; n* l" V, V) P
then; D1 S9 z5 f1 U( ~! U; o
7 |6 T# ]- [* O! ]+ }* |! N) T$ K
#...有参数
  n& X2 B" n* R6 P- }0 W' t$ o! ]/ h1 f7 y6 P
else& q5 s: v* ?3 x! g
8 T8 r1 W& O/ G  }. s4 M
then7 j6 a: u' Y0 U, k* v  m" z
1 e/ i4 U0 l7 L7 p1 P$ r: _
#...没有参数
  U2 I3 D0 `- y+ V4 Y3 s! ~8 m* f* m8 |
fi5 V1 E- U) I; n7 h6 e

  \3 |! P8 o, y1 q手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
# i; S& \% P" D0 l2 M3 s, l6 _! T; h4 J. w8 [
2. getopts/getopt
( k7 [* {  U' U+ q6 p' z" x
* u% A" i  w7 O: a, F$ K2 H9 f* O处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。先来看看参数传递的典型用法:, s0 y/ _7 q) v- ]- Q
8 h  h: k7 \) t3 `# N$ M
./test.sh -a -b -c : 短选项,各选项不需参数" F5 M( q( R: \1 g' [

/ `! l# V) I7 P* A) [9 t; d! n. e./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
) p2 C2 g8 f6 D/ P; i, Q& h
: M" [5 a" g- g, w* n; \7 ?./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。# P! x- B; o7 A* m& S

' a5 n/ d. q5 p+ f( d0 J9 b$ l./test.sh --a-long=args --b-long :长选项
1 k, G8 r$ s$ m, `- f: E6 t
1 h3 y) p1 a; \# ^我们先来看getopts,它不支持长选项。使用getopts非常简单:--test.sh
- x' r+ |  X4 o/ j1 `
; P2 k: y+ _) d[vb]% g& H9 Q; i  M1 Z- l) @
#!/bin/bash
% Q9 S: P# b/ _. X3 S/ P
# B: k3 ~- a! m#选项后面的冒号表示该选项需要参数" u0 r% u3 J  Q' P# f- M1 z8 d" @# n
  q2 U" o6 ]/ U) v5 U! a2 b
while getopts "a:bc" arg* R' \7 O. B: d
! Q% o" u# \$ N- @* |
do
& |# p0 ?' A. t6 I, Y2 }& {# ^  L9 Z% t
case $arg in) t2 k3 Q2 T$ n2 n$ T3 ?  J

, f; C/ t$ i. h) xa)
- u$ `0 x9 S  ^$ O; E! ]# b# B7 c
#参数存在$OPTARG中
$ V# c' b, y  l5 j" v# I1 L2 E! z; O
echo "a's arg:$OPTARG" ;;; E' D7 K5 w$ k, L- G5 t

* n) K3 R& c- B! J, }+ T' q4 F0 D9 lb)* e2 F  k# ^* P( c4 B5 R
9 A6 B1 u3 Z$ P& u+ ~" P0 A
echo "b" ;;( J( z  g' J% j( b, z  T: I! k
9 j% Z4 `' h% Z6 T7 H
c)- v% T5 X# m! W  D0 x. U( s' f

, e/ `: r# `+ C4 F1 O" B: @echo "c" ;;
" U' I# p  {1 M9 k
! d; n/ L" L. C- u  G7 o. C# g?)3 r, G! n* P6 A& X/ B- {

6 Q0 e0 i9 \8 q9 c. ~#当有不认识的选项的时候arg为?
3 k' o1 @/ {, F9 ]
+ A8 w# L# g" g2 ?* K  L  K% A3 techo "unkonw argument" exit 1 ;;8 p( H- c; o7 |* [$ ]; m

, F7 D2 @/ V* d9 a2 R' r6 Yesac
. p- X0 @6 I4 X% L1 o, F8 j
  J/ i* B( F5 Pdone
9 q1 P/ @8 Z9 @1 i3 `. Y8 w
$ g$ I% W6 f& G5 e" g现在就可以使用:./test.sh -a arg -b -c 或./test.sh -a arg -bc
. W0 v; I7 e# j1 w
1 c- c8 O# ]* `: ?# s来加载了。
! {. M1 a- ^' j; Z5 x
: q7 x: W# w: V+ _应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.下面是getopt自带的一个例子:
* y% c9 i! g7 {" A& N. N: f1 ]% i+ D2 h: |2 G# `
[vb]) X( d3 K, z; }5 U; E7 j2 \
#!/bin/bash2 }5 r( B& D' P

# [  W1 ^+ m- c4 ?; E# A small example program for using the new getopt(1) program.
$ G0 B- c* _3 z; ^$ P! O" m/ f# @: t1 _% V
# This program will only work with bash(1)
7 b" o( U8 I! J7 V; v9 v
* S/ a# J, _) \" H$ b2 r. ?# An similar program using the tcsh(1) script language can be found
$ h0 R% b' T$ U/ k" ^" h% P! y' Y+ ]) j; I3 {7 ~. m; P
# as parse.tcsh; O+ ?# U( @3 r% [

; A) i: Y/ P+ A* T: `( \# x# Example input and output (from the bash prompt):- c/ q2 b( n, U* s
3 _7 {- M' ^( U/ \8 g6 p3 E
# ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long ". O* k7 T2 j, b0 `4 ?: `9 O
& d. O7 U! t3 Q8 r9 p; K
# Option a
8 U9 Y: J7 u+ K/ Z+ ^8 \3 P* z+ ?! \: Q( f  Q' g2 L' G
# Option c, no argument
, ]5 k+ _! E6 k4 ]1 i
9 z+ \1 E8 T1 T* y' h# Option c, argument `more'" T7 h. L3 v, W/ }3 z
! g" S: C8 f9 V2 O: O
# Option b, argument ` very long '# _: j  z3 M, e# u4 k) O

; C0 y  ]9 h4 W6 {/ S) P+ P# Remaining arguments:
6 R# z# Y1 V+ ?1 f5 j- T8 r4 i# s. x# |5 |8 l, T$ s8 q
# --> `par1': s9 z6 M& q, l6 ~- j
: \6 O- O  _+ @: z# i: z
# --> `another arg'- y. E& [3 E( k# g% t

: c$ D, ?' V* }+ C; U. H# --> `wow!*\?'
2 c. b# n- _; K7 L5 ^2 h
4 [# q& B3 w+ K6 O, u' k, E# Note that we use `"$@"' to let each command-line parameter expand to a$ P' N! Z4 P" N7 T1 W) R2 ?, a/ P
! e: u/ E7 k- i/ k0 h0 j4 W. w
# separate word. The quotes around `$@' are essential!
; {/ A% I& C- k  _; F" A; v- c9 v- Z, I1 X
# We need TEMP as the `eval set --' would nuke the return value of getopt.% H; L3 ^  q( N, Z; d
$ `7 C% ^5 f+ J
#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项. p5 g( I% j! {! h9 Y* G8 n! W. {

# [; ^' u; v, N$ H. m' Q#如-carg 而不能是-c arg
2 k2 u! Y: X0 Q0 M  X; c/ x5 w2 F  z1 }) e! a
#--long表示长选项
' f" x) P/ y. v6 ]4 ?$ y
. H, p# B/ e0 `  ~! G  f, ^5 N/ Q#"$@"在上面解释过( K" u9 |- D& {0 A( K5 k+ r  q6 A
/ i8 U0 O, {0 p7 V; U3 [
# -n:出错时的信息
5 U+ G1 g) ]" W5 r- O4 H9 @$ C" \5 a
# -- :举一个例子比较好理解:
% J# x, ]% V7 N& p( }9 Z  x- p9 {0 m: u/ C' C6 C' F
#我们要创建一个名字为 "-f"的目录你会怎么办?1 B/ v+ o5 ~5 H2 |! A+ ]2 g
4 [0 `8 N/ t7 S; v
# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
* u' n3 P% T" F* s! t' [/ G+ m& `! m
# mkdir -- -f 这样-f就不会被作为选项。, L9 k; Q; L: ]' P7 a3 i
* f" g+ I9 Z& a7 K% t3 e2 o1 v
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
& i# A0 u9 H# o! M) l5 B( P+ h9 z1 D$ A) t* v$ O, x! R
-n 'example.bash' -- "$@"`" y) |+ r, y0 a& o) h$ [" q! ?
- ~. L) m: u/ B7 N# o- g& r# M
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # H9 s' W8 Z: _3 E
# Note the quotes around `$TEMP': they are essential!
  Q. r7 X# I8 ]4 l+ k7 u" V2 g
/ T7 a2 O$ x6 N/ ?6 Q#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了1 m: N+ Q2 |) L+ B

# k$ U" ~& t7 a3 c9 {eval set -- "$TEMP"5 M- _4 a& ~4 t! r1 Q( B
; d& L7 f' [! E" B
#经过getopt的处理,下面处理具体选项。
, Q. q5 v0 t2 i8 k  j# _' z
" Z' h- ~8 k! K. ?while true ; do
  K; f5 j8 P/ F: _: K# j6 m! ~
* N+ u; t. I" ~, Z& tcase "$1" in7 x" N% Y8 p" m3 I, }4 y- p/ e" b

8 P- w& z3 u$ G3 u+ K-a|--a-long) echo "Option a" ; shift ;;
$ r+ h$ T7 ?5 i, }
$ D  c% b. n- P' i2 ]-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;1 Q5 s# V7 ~. F7 T" J4 y% E
5 [/ z" |: D" c' L3 ]3 G8 j
-c|--c-long)
# Q8 K. m# h5 ]( T  e
9 U1 {6 O8 A! q, b1 ~! j# F# c has an optional argument. As we are in quoted mode,5 G3 T& a5 d  W7 O# }: E( s
* M/ N1 q7 I+ \& V" K
# an empty parameter will be generated if its optional5 ~# p. g) E  }' @. o; C3 V  o" q

% N) u8 b8 G( g) O8 J0 G( p# argument is not found.
/ O% n+ @1 M- F# G5 W; B8 v$ _0 \4 N0 c) \6 G! Z. }
case "$2" in
- j! d( }0 M6 O& C- }+ u* n( [& [; g' @: c3 e$ ]  s# J6 u
"") echo "Option c, no argument"; shift 2 ;;
  n3 E% r( a& Y1 s# q7 u/ @- p+ b3 I( _) _& k5 H- W# [
*) echo "Option c, argument \`$2'" ; shift 2 ;;- s' z- c* E  W* Q$ G+ r

8 [8 x6 E6 ~, Iesac ;;% m9 a  l& u0 s4 e

' R; Z! D: b& i9 [% m9 ~% n1 r--) shift ; break ;;+ F" w0 Z7 K1 W; i

$ f6 L* H* L( X$ i8 Q+ D+ ~*) echo "Internal error!" ; exit 1 ;;3 _3 e3 k4 J" ~
8 t$ Z* V# D% x% Y# s0 N5 b
esac
$ k5 J( a3 h6 p4 ~, u2 V/ a2 s5 f3 R2 i: _: I
done
6 H" k6 e! y5 o* S! A, e% J$ X8 n, A. ]
echo "Remaining arguments:"/ C9 T! n* F6 _) r6 h. R
: _2 P- S6 E2 R; J
for arg do% h. A6 V" _) q
( T" v$ l& s3 G9 t6 ^* H6 V5 g
echo '--> '"\`$arg'" ;1 s% X& q* [( ~! t' A2 ]

% T4 B. n: \. j, A1 Xdone
; I% P2 t; D1 I: @
& U# v. S2 V. d, B
, L9 F8 d/ C4 |* P1 v- e" F$ \比如我们使用
( v( f1 M: f. u' x
  ]) k" {1 G2 r2 `./test -a -b arg arg1 -c
, H7 X; d9 H' \/ b6 B3 Y) ]3 T6 _7 D8 R) l" I
你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
0 M" J! l4 D, `1 G2 m5 \/ H4 C/ \- e1 R  N4 z! }4 @8 d! o
-a -b arg -c -- arg14 F, E/ d. y6 U
  l0 Z# N8 G7 o* q
$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。1 P6 c) b8 C" o: T" h3 z
2 b+ h1 U2 x4 o' H1 |8 e" g
3. 总结3 A9 Z  t2 [4 _4 h* h( ?1 s

: T5 `# {1 D/ }5 p1 w, A3 I豹尾。
# `5 j5 M* p. f7 j& {" z
2 I6 C0 O, `( _# m$ b; b4 `本文系统(linux)相关术语:linux系统 鸟哥的linux私房菜 linux命令大全 linux操作系统
$ a- F. O$ v( w
* g/ K; f: M4 U0 Y: I) h
发表于 2017-2-22 21:33 | 显示全部楼层
记得getopt常与shift结合使用,while循环一下就好了。
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:39 | 显示全部楼层
efan 发表于 2017-2-22 21:335 n$ j$ L. |" u/ p  r" k
记得getopt常与shift结合使用,while循环一下就好了。

7 r6 \: N6 l9 I0 ^! c3 I请教一个问题
+ x$ o4 [+ L8 H/ W: w有一句 :set -- `getopt -q ab:c "$@"`
2 n; X* @% D( Y0 E$ m+ L请问 这个如何解呢??
1 u# `$ M4 T8 h' c, f4 N
回复

使用道具 举报

 楼主| 发表于 2017-2-22 22:43 | 显示全部楼层
这是全部的语句
' A# p. M4 h! t4 @+ Z) b+ Eset -- `getopt -q ab:c "$@"`7 R6 \* p3 K6 @2 [
while [ -n "$1" ]
3 O- c( n  u  M+ |% d' i' Gdo
; ^8 K$ q1 w( ?5 @  Y3 J/ t  case "$1" in# U; r) N% U6 {/ F1 \3 T
  -a) echo "Fount the -a option";;8 t/ s0 Z* r+ _/ Y

) I/ B6 _5 e; ~/ C7 w; t  -b) param="$2"7 F5 w8 o7 l/ h! D; _
      echo "Found the -b option. with parameter value $param"
8 V/ {# o6 ~: l, K7 w      shift ;;& z, |# i1 J1 {# C5 Y- o
; b  B3 y6 _) ~$ y0 W
  -c) echo "Found the -c option";;$ z$ {0 ]7 s5 I( b" z1 i
: ~7 Y! z/ t+ m  _) v7 G9 B
  --) shift
, Z5 p2 |7 n/ B  |9 X6 d5 `      break;;
9 J' @, a. S& y( _- T9 O* v9 ^- V; m  q- }
  *) echo "$1 is not an option";;- D( z3 ~; k2 H5 ^
  esac% G. W0 j; n, }7 g8 o( H
  shift
! `( n. H! b9 i& r: X* s; L  done" G# Q5 @8 B- ]) Q/ H& F
+ P) d, H. P( S: o- K! c6 o+ c
  count=1. {+ e3 u, {4 y6 ~( \6 N
  for param in "$@"1 |6 u7 r% ~! x3 }8 ?. E, c. ?
  do7 `% N- c8 t0 K, _9 `( c
    echo "Parameter #$count: $param"- z4 }+ }# P7 C$ U4 Z% M( A: M, Q
    count=$[$count+1]( e! H1 p. {  i8 O$ s5 @+ R2 C! ~
  done+ {2 H( p& z# X% U! X- f9 I) c. H( E
回复

使用道具 举报

发表于 2017-2-23 00:12 | 显示全部楼层
kenson 发表于 2017-2-22 22:39
8 Z$ t; ~* D0 S' t请教一个问题4 u! |& S$ o' R6 k( f9 E+ U
有一句 :set -- `getopt -q ab:c "$@"`
1 D1 n: K  N# i; [! F9 ?请问 这个如何解呢??

  o$ t7 G: s$ m0 e. y6 j请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
9 H& K8 S# u/ ]0 T- ^
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:44 | 显示全部楼层
efan 发表于 2017-2-23 00:12
3 {2 I+ p2 @9 c2 V请教绝不敢当啊,当时也只是学了个皮毛,只会非常简单的应用,很惭愧现在都已经忘了
. `% o( I' d9 i" }* p* u- e2 W
呵呵没关系,大家一起学习呗。/ @+ k. V& H: s
经过一晚的思考,我发现了之前我看到的一个语句:set -- -F5 [5 D" w6 R- A( o/ F( x5 A
一查在shell 上用echo $0 $1 会显示bash -F,也就是说这个是设置位置参数的," C+ B% {: X3 c) u8 `( P
所以set -- `getopt -q ab:c "$@"` 其实是getopt返回参数给set 作为位置参数用的。
9 k+ F/ S; o5 V$ w! |2 K: B如:getopt.sh为文件名,./getopt.sh -ac 它会在位置参数里显示$1:-a $1:-c $2:--
! b" B$ `/ r; K, h$2上会跟着一个“--” ,想不明白,但也没关系知道怎么用就可以了。
/ \4 O8 q: C! r补上昨天调试的代码
  x. b/ H  T/ }% X' r
* h$ @- `) Q& [2 t( y. L1 M4 J#!/bin/bash
: x& g: T4 c* oset --  `getopt -q ab:c "$@"`3 ~1 W1 W& S$ S" m) M: h
tt=`getopt -q ab:c "$@"`0 L8 L) L# w- [- N$ H6 w1 |
echo "\$tt:  $tt". c% M& `* m! P* ~; |1 r
echo "\$0:   $0"
1 L4 |3 j" Z+ H) y' iecho "\$1:   $1"
' f' W, z6 j8 ]) hecho "\$2:   $2"
6 G# F9 E* }1 F1 ?0 ~echo "\$3:   $3"
$ w6 S9 D$ x  pecho "\$4:   $4"/ ]2 J+ \- r2 f7 v! b
echo "\$5:   $5") ]0 `* C5 g  j) p% I0 o3 L
echo "\$6:   $6"
& q! X% s% V7 \echo "************"
* o) ^( C# J& A4 ^' V: F  h" O
3 t; s' W( Y( ]; M3 f& v0 K2 s
8 v, \( F$ c: [3 I1 w* r; h: E- v, K. U  n& `) B( Q" D
while [ -n "$1" ]- E9 v" l0 r0 P3 Z+ a9 r
do# ~$ x6 F4 f. t
  case "$1" in) X- Z' V0 b" ]& g
  -a) echo "Fount the -a option";;
% h. T5 m+ q5 P2 @" U. @4 N, `) l; o4 A% K. W
  -b) param="$2"
6 t" k1 X. H, T4 `0 w/ v1 r' a      echo "Found the -b option. with parameter value $param"
- |0 }* g7 L* }# g* z( p# @2 _, F      shift ;;: l3 y" Y7 R" F$ Q: s8 p
; C/ D0 q, r9 K. v/ ^
  -c) echo "Found the -c option";;
) m  t0 {! ^7 R* f
: c9 m3 _- S  Y) j. ~  --) shift
: E: M. c4 o+ a& z      break;;
3 o' a  Q( v1 p  b7 j# [: [  S
/ ]3 v0 w; x8 h; K& G! e  *) echo "$1 is not an option";;
& c, Q7 C; L, Y8 ]# Z5 S  esac
  k' ~0 l7 M" e# D  shift2 p; f) s* G' B8 z
  done
) o, O; f% w% N# y
5 W" @" [. p  ?  count=1
7 _+ C6 R. n7 }) b  for param in "$@"
; d+ {+ s. G( n  {" \  u  do
1 n; Y0 z6 L* K7 N    echo "Parameter #$count: $param"
! i& O* u1 ~8 B. {    count=$[$count+1]
; n* y# p+ p  Q8 f! H  done
" E# @/ l- M  {3 d  _- u) D5 M1 r4 g# R+ G- S
1 @, L. h& `0 h, D4 P2 ?
: {5 L0 o% G- g, Q
回复

使用道具 举报

 楼主| 发表于 2017-2-23 08:46 | 显示全部楼层
这样子你可以这样用法  ./getopt.sh -ac -b test
5 @. W# c) t: y& C. v$tt:   -a -c -b ''\''test'\''' --
( z1 @) O* p, r0 k% k$0:   ./getopt.sh8 }% j2 h, O* g- f  h
$1:   -a: d# _3 M. J' e
$2:   -c# E. }9 V* S* i( t0 P& M6 z* G
$3:   -b. }7 F! M6 r- X  o# j' H% q3 a
$4:   'test'6 p, z: \: `8 O% T: n
$5:   --* r! I6 o- I* H4 N" q
$6:   
3 C/ ?! G& E4 T# {************
4 d- u) P% I- PFount the -a option2 V  L! O; _* B; L4 `7 E5 M  O' R. K8 W
Found the -c option
: A0 U! {9 w6 j" VFound the -b option. with parameter value 'test'
+ U7 f- l  u, e; O4 Y0 M* k
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:00 | 显示全部楼层
getopts 的用法
. a7 y" b1 q% Z0 y. ^: D4 E( Ugetopts跟getopt 差不多但有一些区别,区别在于比getopt简单一些。
1 B  A( b$ y- u* q+ J5 h# I0 N代码:
8 i/ V( e4 Y( |0 X- a6 Wwhile getopts :ab:cd opt  Y. L/ W0 V* x. H1 j7 a$ ^  s5 C
do
2 ^  }: x0 Z; o- |* C2 i   case "$opt" in( _3 H" o' u2 F3 f/ p/ L4 L
  a) echo "Found the -a option";;2 k9 y0 }! D9 O8 x- ?
  b) echo "Found the -b option. with value $OPTARG";;
' D& J6 w! K. k  c) echo "Found the -c option.";;$ g# y: j3 z. q) m% Q
  d) echo "Found the -d option.";;
& s, U6 S  T  \4 I8 ?  *) echo "Unkown option: $opt";;
0 y* S" O' M+ W$ N& |  x9 _4 U- K  esac
( c1 P' i( @; U) ^8 R1 udone
8 m) i8 Y* ^$ h5 o; ishift $[$OPTIND -1]* J/ j1 G  V* i4 y. T5 _% g

+ {: g0 M9 }  c" a- Z) Tcount=19 y; q  G( y) Z! H% s, d  n; E
for param in "$@"& }7 s3 E& P  y! k" U. i
do
: S) E. c2 T/ b1 r   echo "Parameter $count: $param"
6 y$ j" N0 Z1 x. r$ I8 Y1 s  count=$[$count+1]
  T; v! z" L4 Q% ?* w4 Ddone
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:05 | 显示全部楼层
其中OPTARG是一个环境变量,如果选项有一个参数值,就会保存OPTARG之中,OPTIND环境变量用来保存getopts正在处理的参数位置。
9 ?( G, i; G( k2 q其后就可以这样用
$ A2 Y& G! ]# A3 B3 C" C  h  {./getopts.sh -a -b test1 -d test2 test3 test4' e5 y: J# j5 X* n, g. b5 q
./getopts.sh -acd -b test/ }- k' i# s. t5 L/ C4 c
./getopts.sh -a -b test -c -d test1 test2 test3 2 D4 O9 i1 C7 Z6 p4 N
等等
回复

使用道具 举报

 楼主| 发表于 2017-2-24 14:27 | 显示全部楼层
我将代码改了一下#!/bin/bash
, q$ o2 [2 a1 }: s' Z5 \6 l! N- _' [
, H  G: {3 u7 b+ g% z# F! o0 ?( h) S9 U% z5 j# @9 O5 S
while getopts :ab:cd opt
) w7 ?( m" q: T5 W" Y4 D2 ~  Pdo
; O, j3 Y* l. G, }  case "$opt" in( `7 B4 L/ O) E8 |! t
  a)echo "Found the -a option";;
3 i* e6 M. ]; c. a: M/ Y- c5 ~  b)echo "Found the -b option. with value $OPTARG";;
* M  g( d, ]/ h1 P7 y; C+ {  c)echo "Found the -c option";;  s* H0 q  b/ d
  d)echo "Found the -d option";;$ ?' K/ i& P/ W/ @3 V# t
  *)echo "Unkow option: $opt";;7 F- Q# k# z1 v2 a
  esac: K: G, ^0 @+ F' V9 e- ]7 M. I
done
3 a- Y$ p9 v( G. w; w) g( Y9 P1 e% o+ N! X  ~
echo "**************"
9 z; L2 \$ ~6 [2 }) z2 o echo "OPTIND: $OPTIND"" y6 G4 c6 i4 ]  M2 q# Y
echo "\$@ $@"! z3 b' |0 }' |8 v8 c1 x  |( a
shift $[$OPTIND - 1]
$ g( q) ?$ f2 Z& D: R2 b echo \$@: $@
' }4 u/ Q5 W- T- S echo "**************"$ f. ^2 S! b  x& @7 X: T
1 {& }$ R  l7 p' _5 m& u5 ]$ ]* M9 q
count=1* v' N" a7 f* f. z; O
for param  in "$@"
+ s1 P( n/ ?% zdo. e- g4 o0 l5 \" T: Q
  echo "Parameter $count: $param"
/ h& f  A' S! I# A% X- k6 K  count=$[$count+1]
+ L1 r) h, J1 Y' idone
. J/ v' W) k& _8 I: `6 _0 `* ^
9 P# ]: [6 i- J: e" Q/ K" O  L$ p2 @6 l) B5 |- ~2 ?
5 v$ u0 e# X/ ^6 W# G' s' w
其中有一句  shift $[$OPTIND - 1]  这个是用来改变$@中的参数的排序,不然之前的 -a -b 之类将没办法跳过. n; J2 |6 p+ a: M7 Q

& }$ W; v3 J4 w$ y* Y
回复

使用道具 举报

本版积分规则

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

GMT+8, 2025-10-28 14:26 , Processed in 0.035220 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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