设为首页收藏本站|繁體中文 快速切换版块

 找回密码
 立即加入
搜索
查看: 1255|回复: 1

Gawk手册

[复制链接]
  • TA的每日心情
    奋斗
    2019-2-12 09:32
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    累计签到:1 天
    连续签到:1 天
    发表于 2008-6-12 16:31:32 | 显示全部楼层 |阅读模式

    马上加入,结交更多好友,共享更多资料,让你轻松玩转电力研学社区!

    您需要 登录 才可以下载或查看,没有账号?立即加入

    ×
    GAWK
    # R. ]5 x8 d9 x$ K% A! Q第一章 前言4 p2 S$ L& U, s( |: l0 Y
    第二章 简介1 F* C' {! e( j9 H0 ~
    第三章 读取输入档案, Q+ z! D  E" E8 b! x/ x! `
    第四章 印出
    0 E+ @9 Q8 z* ~# a! V% c1 c9 X; w第五章 Patterns4 d% I# C0 `* V+ Z: M5 K/ u
    第六章 算式(Expression)作为Actions的叙述$ n. X% H+ X/ j- o6 M! w
    第七章 Actions里面的控制叙述
    . Z" v8 l- S7 P7 G第八章 内建函式(Built-in Functions)
    ; E& P; i5 k" C& s3 M. g6 D3 F! M第九章 使用者定义的函式$ P, T7 i+ D1 y
    第十章 □例3 ^2 L$ d3 t6 D3 D8 x/ z' {, I" R
    第十一章 结论9 w$ r4 j9 s2 D) P5 [* q

    # W7 |7 x* B; h8 B# I=======================================% e) K6 |) r% }3 ~. x
    第一章 前言$ z' F1 b# M% b( H! Y/ @
    awk 是一个程式语言,对於资料的处理具有很强的功能。对於文
    3 }" R4 W* V& T' E7 e字档里的资料做修改、比对、抽取等的处理,awk 能够以很短的程式* W0 D. N' g, R1 q
    轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作,
    * Q( I3 d9 G8 ]; L# r4 `; H会不方便且很花费时间,所写的程式也会很大。
    # S3 p& A. v# S- Oawk 能够依照使用者的定义格式来分解输入资料,也可依照使用8 k% `/ q; g7 [5 B3 h  Z
    者定义的格式来印出资料。
    / R2 ~/ j( N, v- b5 S; L) nawk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名
    , H) x) g$ F0 P0 {, T6 }7 M:Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。7 m! n# ?0 P( X
    awk最初在1977年完成。一个新版本的awk在1985年被发表,它的功能
    + z1 R, T7 G* |2 T& h0 h比旧版本增强不少。
    * X( h4 h8 `( c" w3 z5 B  `7 w4 Tgawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不断地& ^# T* _; K/ X8 A4 d9 i/ c% i
    被改进、更新。gawk 包含 awk 的所有功能。
    $ g. h! v6 T1 n1 N! h. ?  q往後的 gawk 将以下面的2个输入档案来做例子说明。
    4 u0 b( N+ c" G7 X) U档案'BBS-list':7 B; W! e, A+ u: @
    aardvark 555-5553 1200/300 B  A( |( J7 U5 q& `, |% ^* }
    alpo-net 555-3412 2400/1200/300 A
    5 ?4 j1 B7 O: H* Abarfly 555-7685 1200/300 A, \' v7 @  {% b2 d9 H
    bites 555-1675 2400/1200/300 A
    $ c- F, r. Q5 w2 ~5 Ncamelot 555-0542 300 C
    + W& q9 Y4 r/ r6 y. T/ T# kcore 555-2912 1200/300 C
    6 F1 A) O9 R, y0 ~* ]fooey 555-1234 2400/1200/300 B
    . y) J  c- x7 O0 r% ?, pfoot 555-6699 1200/300 B
    0 e! D4 L, f' _4 @macfoo 555-6480 1200/300 A! u0 m% B( G# W7 W" T5 [' P
    sdace 555-3430 2400/1200/300 A4 C/ \6 p) y8 g; J
    sabafoo 555-2127 1200/300 C
    4 U7 \8 P% I4 B! v档案'shipped':1 k1 z+ \" y2 b* g# n
    Jan 13 25 15 1153 ]4 v+ o$ _; _6 f& _/ ]! x
    Feb 15 32 24 2269 t" d; G2 P( [, X" |& A- I: R
    Mar 15 24 34 228
    : `8 F! h1 ?' C7 C( Z1 j& ZApr 31 52 63 420
    2 S; a  M* j/ ]" b8 e* M; [May 16 34 29 208
    # U& W/ ^" Y+ zJun 31 42 75 492
    9 t1 T, N) f8 C. A) oJul 24 34 67 4364 c* N  J2 R  Q+ P3 V
    Aug 15 34 47 316
    ( @4 a2 L) ]4 mSep 13 55 37 277
    3 n0 x9 \/ ~" P: w! X/ ~$ dOct 29 54 68 525& b; i# m& C3 k3 d4 b; b6 p' _
    Nov 20 87 82 577! G' I6 d1 F( Y4 k% J  }7 ]
    Dec 17 35 61 401) X1 Z- M- j( y2 C3 T' d
    Jan 21 36 64 620
    " K, R$ ?# p" E. ~& `& [3 U& YFeb 26 58 80 652, d# k* J$ a8 J# c6 R) p7 D
    Mar 24 75 70 4952 F; S9 n+ T! O1 a' N- I* W
    Apr 21 70 74 514
    , R, f# T7 F3 o6 I. S
    8 A6 E, y( H* n; `第二章 简介' S5 q: k3 N! b& H2 k
    gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns
    % p+ T" @' `9 G6 F- B。当一行里有符合指定的 patterns,gawk 就会在此一行执行被指定
    : A4 s& i+ e0 E0 }的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结
    $ f5 r4 O6 h2 X; l6 e束。
    : S9 s6 _7 k6 n' k7 U* H4 X- Dgawk 程式是由很多的 pattern 与 action 所组成,action 写在
    # ~7 @# [5 y, t  M: l/ g. d% G/ H大括号 { } 里面,一个pattern後面就跟著一个action。整个 gawk 程
    # E- M8 r1 ?# ]) e" Y( U2 N式会像下面的样子:
    / g. n/ }* B' N0 j4 X& K- @) ppattern {action}" Y1 I" l* `. X7 S  W3 A
    pattern {action}
    * f4 n1 Y  m0 S& K5 r在 gawk 程式里面的规则,pattern 或 action 能够被省略,但
    0 _6 @- z3 b. n' f+ }是两个不能同时被省略。如果 pattern 被省略,对於输入档里面的4 S4 T) W+ c# u
    每一行,action 都会被执行。如果 action 被省略,内定的 action
    . D5 z2 I" z: ?! N' m5 ~1 V$ L! G* }8 ^则会印出所有符合 pattern 的输入行。2 Z/ ?4 ^4 m1 N1 _7 F% R

    * y1 r/ v7 t1 v& d' q) A2.1 如何执行gawk程式
    3 y% _& w$ n# @5 J- ~$ {4 ~基本上,有2个方法可以执行gawk程式。
    8 }; P+ d* e/ ^& `/ ~2 g  O□如果 gawk 程式很短,则 gawk 可以直接写在 command line,如下所示:8 G5 Q# r' h2 t' j# V# r6 o( |* o
    gawk 'program' input-file1 input-file2 ...
    4 j7 G3 B" Y# j% d/ D+ b5 d其中 program 包括一些 pattern 和 action。; b2 o& ^* P" o+ ?
    □如果 gawk 程式较长,较为方便的做法是将 gawk 程式存在一个档案,
    % {3 i7 Z5 J5 q6 c0 b  Q' U0 @即 patterns 与 actions 写在档名为 program-file 的档案里面,执行8 P# G4 _+ m) g
    gawk 的格式如下所示:
    9 d5 b; t$ i6 M. {2 ^gawk -f program-file input-file1 input-file2 ...# x  J5 |6 O' B/ L# e
    gawk 程式的档案不止一个时,执行gawk 的格式如下所示:
    ( p  ?+ F4 D' O0 s& v- m  t. Bgawk -f program-file1 -f program-file2 ... input-file1
    * X) L& h0 d5 }5 M6 L; Oinput-file2 ...- ^% ^/ q/ b3 b/ {" a7 @

      G5 e" p/ U& D$ b1 p( D2.2 一个简单的例子/ R) x) ^, u2 ]) y+ ?$ T) V
    现在我们举一个简单的例子,因为 gawk 程式很短,所以将 gawk 程
    9 P( e: |' W& ~% t' P. p- e式直接写在 command line。, z7 D% i6 q7 j+ X
    gawk '/foo/ {print $0}' BBS-list
    8 ^, ]' D, x( Z5 O: k, ?* x实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern,意思为搜
    - }) |/ b9 e. P3 r1 _3 Z* ^2 g; W寻输入档里的每一行是否含有子字串 'foo',如果含有 'foo' 则执行 action。- f9 o, s) Q4 c3 [+ x; {
    action 为 print $0,是将现在这一行的内容印出。BBS-list 是输入的档案。" K2 @* Y9 Y7 e. R" ?
    执行完上述指令後,会印出下面的结果:) O1 u- r2 z  x- `: P! X1 _
    fooey 555-1234 2400/1200/300 B
    " \# s, g" x. E7 r! o4 ufoot 555-6699 1200/300 B
    5 l+ A' P4 z1 l: cmacfoo 555-6480 1200/300 A) w& F5 R6 L5 X# u, G: p7 \. [
    sabafoo 555-2127 1200/300 C9 z4 L; L* O- P  I( Y

    ! V8 H2 O" D4 h: j9 p: \& ]" [4 B2.3 一个较复杂的例子
    ) {4 w  B1 t, z4 M1 e$ vgawk '$1 == "Feb" {sum=$2+$3} END {print sum}' shipped
    ) n: i. D: A! r+ A2 {' i  D现在这个例子会将输入档 'shipped' 的第一个栏位与 "Feb" 做比较
    4 V7 a8 ~2 U, U! c& |,如果相等,则其对应的第2栏位与第3栏位的值会被加到变数 sum。
    + @0 {( ?1 C0 H/ z4 p" _对於输入档的每一行重复上述的动作,直到输入档的每一行都被处理8 x8 H+ B- p. F" r+ d
    过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输
    : O) W3 D1 |+ j/ Q9 ?- ?. q/ a- u入读完之後,执行一次 print sum 的动作,也就是把 sum 的值印出。0 r! a6 r: X4 j7 z
    下面是执行的结果:
      P8 H' ^, d/ a* z84! G/ R6 \  k: ^/ S

    - w# l: X0 i! t  b; g第三章 读取输入档案  C/ \$ k3 P, k& B5 @2 e+ e
    gawk的输入可以从标准输入或指定的档案里读取。输入的读取单5 H& g8 N& S  L3 l: Z: ?
    位被称为”记录”(records),gawk 在做处理时,是一个记录一个记
    . a. c* ^0 W- v录地处理。每个记录的内定值是一行(line),一个记录又被分为多个
    . Z# ^8 O, n, O7 a. O! r栏位(fields)。
    7 f% d$ P! Z# l( l( s& U; x$ x) x0 [9 O
    3.1 如何将输入分解成记录(records)4 ]$ B; @4 z+ F& }' R; }7 M1 q
    gawk 语言会把输入分解成记录(record)。记录与记录之间是以
    , n- L( j/ Z) d! U: _2 E2 |) u; q( yrecord separator 隔开,record separator 的内定值是表示新一行的
    ) T8 R' g: `% z5 {2 n& e字元(newline character),因此内定的 record separator 使得文字3 d- ^) z5 h' O5 |$ ?9 a, L" [
    的每一行是一个记录。
      a$ [# @) D) h$ v7 G9 X1 @record separator 随著内建变数 RS 的改变而改变。RS 是一个字串,
    % k, ]; K- Q0 D, S它的内定值是"\n"。仅有 RS 的第一个字元是有效的,它被当作 record
    ( y$ O7 d7 Y2 D6 [# ~! T; Mseparator,而 RS 的其它字元会被忽略。
    + X4 h* F% l& k# t! e内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内
    . d% h# v7 ]: o5 F; v" Y建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。5 A  Y. C' ]3 Y% q. u5 {9 U
    : s# h6 e: m2 w. V+ {/ x6 q
    3.2 栏位(field)
    4 s  [4 k0 T9 ~, J$ i0 \gawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一
    , X9 S, b6 T! ?3 G% {行里面,gawk 的内定动作会认为栏位之间是以 whitespace 分开。在9 x2 i1 k0 j% X/ `, u: @. C
    gawk 里,whitespace 的意思是一个或多个空白或 tabs。3 T" G; F! D, j( K
    在 gawk 程式里面,以'$1'表示第一个栏位,'$2'表示第二个栏位
    * X- u: i% ]5 l: P& k,依此类推。举个例子,假设输入的一行如下所示:6 I  g0 ]" m: s; X' X8 e
    This seems like a pretty nice example.
    0 ~% o* N# I3 L5 O. D1 y第一个栏位或 $1 是'This',第二个栏位或 $2 是 'seems',依此类推。
    2 r; G4 i5 t4 Q$ n7 V有个地方值得特别注意,第七个栏位或 $7 是'example.'而非'example'。- L5 T# |, p: ~3 H# |4 }
    不论有多少栏位,$NF 可用来表示一个记录的最後一个栏位。以3 {' |) R2 m  ^3 p4 K
    上面的例子为例,$NF 与 $7 相同,也就是'example.'。3 D5 }: M8 X" C+ h) ?6 s4 H( ~- D
    NF 是一个内建变数,它的值表示目前这个记录之栏位的个数。( U* z1 L2 U4 D( R: j& o
    $0,看起来好像是第零个栏位,它是一个特例,它表示整个记录。
    2 {. n- Q/ K# r! l. X" c, a9 A下面是一个较复杂的例子:
    4 K: n7 S# z: q6 ggawk '$1~/foo/ {print $0}' BBS-list2 I$ m! E( N" n9 ?( R# ^# I, A: k
    结果如下:9 M+ x  |- K* g, u
    fooey 555-1234 2400/1200/300 B) n$ L3 K5 s' \5 p# K0 ^
    foot 555-6699 1200/300 B
    + s/ u9 K1 b- wmacfoo 555-6480 1200/300 A% p3 i" j/ G1 c# I5 ~4 Z
    sabafoo 555-2127 1200/300 C
    7 [3 B6 `, v8 `- P这个例子是把输入档'BBS-list'的每个记录的第一个栏位作检查,如  z. W" m* s- V* B: l
    果它含有子字串'foo',则这一个记录会被印出。
    5 e* m3 R1 T: b
    $ G2 U& J% r- \$ c6 T3.3 如何将记录分解成栏位+ Q* `0 `9 v6 I
    gawk 根据 field separator 将一个记录分解成栏位。field sepa-
    8 t6 G. @$ d! X$ [0 w1 z  Q' G* f3 Grator 以内建变数 FS 表示。' K- _* S" M; P1 P" ^% m
    举个例子,假如 field separator 是'oo',则下面的行:+ @$ k( G: ~9 X$ o- h% a
    moo goo gai pan  l: A# [# ~- C: R* y
    会被分成三个栏位:'m'、' g'、' gai pan'。, z6 m  w4 a" }( ?! n8 R
    在 gawk 程式里,可以使用'='来改变 FS 的值。例如:" L: R3 T% B& ^: A  d
    gawk 'BEGIN {FS=","}; {print $2}'( q$ _0 i! w" R( f( l9 ]
    输入行如下:
    * E# [6 G; d+ H9 _John Q. Smith, 29 Oak St., Walamazoo, MI 42139
    3 ]( P4 i, h; s! w+ e, j执行gawk的结果将印出字串 ' 29 Oak St.'。BEGIN 後面的 action 会在- W6 r: A. {+ ?/ `
    第一个记录被读取之前执行一次。( P* j5 x( S+ Z+ Y# }1 }+ D
    * G# M3 k) x9 r* \" W) c
    第四章 印出) A0 J' F# o' J8 V
    在gawk程式里,actions 最常做的事就是印出(printing)。简单1 W* J: Y7 K" p
    的印出,使用 printe叙述。复杂格式的印出,使用 printf 叙述。6 A0 b2 T; ]3 E1 Q! N+ n+ N1 ~- z

    : D% @$ q/ [! Y: N5 k. q- S4.1 print叙述
    * z% A, [% c3 _2 }& jprint 叙述用在简单、标准的输出格式。叙述的格式如下所示:& T5 j2 P0 Z' {  }9 l
    print item1, item2, ...$ o# L/ T- b9 C, u
    输出时,各个 item 之间会以一个空白分开,最後会换行(newline)。0 q7 b. ^3 Q6 I& g& j  b2 a! i! L
    如果 'print'叙述之後没有跟著任何东西,它与'print $0'的效
    5 K# J# g( u1 u3 P: x果一样,它会印出现在的记录(record)。要印出空白行可使用'print5 J  _1 P7 N+ R  ^
    ""'。 印出一段固定的文字,可用双引号将文字的两边括起来,例如7 [0 Z. G7 U- x: p  B1 {, o/ E
    'print "Hello there"'。
    * u0 @% s" P+ O$ J这里是一个例子,它会把每个输入记录的前二个栏位印出:+ l3 x* H" |; T
    gawk '{print $1,$2}' shipped
    , _3 {9 z$ u% V0 r结果如下所示:
    1 J* q3 U% }8 P7 ~Jan 13
    7 Q/ J. y! l. H& T  FFeb 15
    ' z7 V+ R; {- u/ W4 `1 {- R1 ~Mar 15' f' p" B. B: Q
    Apr 313 U( b# a& r8 Y" O
    May 16, N3 H- Q" q# x1 d
    Jun 31
    ( V% N% r- ?! T8 g% ^9 n* B" aJul 24! q5 [7 e4 i+ ]" z/ x( W; E
    Aug 15
    1 u' k" P. b" v7 m6 s0 G% JSep 13
    9 X7 p( i$ W! i* S' l' M& FOct 29  O9 l5 ^4 {+ E" H/ D, e5 {/ n! y
    Nov 20. D, Q9 I9 n7 c" h# {1 U9 @4 \
    Dec 17
    & J9 R/ d  C2 h$ h9 V) `Jan 21
    + y+ m& K+ I% W8 p. sFeb 26" ~* w$ {# i; c6 t0 }9 j' h+ B. x/ }
    Mar 24
    8 G3 L6 R! J' y' ?# L% EApr 21! w/ y5 c1 ^; F+ z
    . [/ s" [+ A; {5 d! u! [
    4.2 Output Separators
    ) m# ~4 h: o! o0 Q' _2 w) x/ C前面我们已提过如果 print 叙述包含有多个 item,item 之间
    ) h* u5 t2 ]+ O" d用逗点分开,则印出时各个item会被一个空白隔开。你能够使用任何
    1 F" b! C% o% a3 N0 |+ a( ~的字串作为 output field separator,可以经由内建变数 OFS 的设5 o# J1 Z% R$ `7 Y
    定来更改 output field separator。OFS 的初始值为" ",即一格的8 w/ _& L/ v* o. U9 t
    空白。
    - P8 E8 O/ q1 }  x' `# s整个 print 叙述的输出被称为 output record。print 叙述输4 l0 u8 M! F2 m) \
    出 output record 之後,会接著输出一个字串,此字串称为 output/ |% o# d  d' q: d/ \$ Y$ U
    record separator。内建变数 ORS 用来指明此字串。ORS 的初始值
    7 x, w5 M( f/ k3 b为 "\n",也就是换行。/ m3 S6 m; \. `1 v, G; B
    下面这个例子会印出每个记录的第一个栏位和第二个栏位,此二( m" G" A+ `- |/ |8 [  Y( D8 _
    个栏位之间以分号';'分开,每行输出之後会加入一个空白行。5 ^" `2 i3 D  n1 \, S0 A
    gawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list" W; F/ K. c$ V7 Q: Y" o
    结果如下所示:
    3 e7 ^- _7 U3 G- E/ B: waardvark;555-55533 K0 z$ H, p4 [. n3 N) W
    alpo-net;555-3412
    + p) ~0 s2 K: Z( t: j( J, qbarfly;555-7685
    / J) q6 m3 G& G3 @$ }' t5 X7 Pbites;555-1675
    5 U' e9 n) d& J0 `% O5 f" kcamelot;555-0542: g/ F* L8 x0 ^, G4 F$ M9 X8 x! e
    core;555-2912( p# l* R* G, V6 p
    fooey;555-12344 h8 r0 m+ q5 X$ G
    foot;555-6699
    - t2 W8 b  Q1 J# v2 w* O/ jmacfoo;555-6480
    ) @2 n) a8 w$ ?0 Lsdace;555-3430
      O& p* D8 Y5 _% esabafoo;555-2127) z4 r: z: \! g, s

    4 t4 V! v- W1 `% I; Y+ \4.3 printf叙述
    9 e. b$ }3 ^, ~printf 叙述会使得输出格式较容易精确地控制。printf 叙述可以
    " R) @. @# N. q1 B$ u2 p+ y$ m指定每个 item 印出的宽度,也可以指定数字的各种型式。
    * ]- P. b6 d' nprintf 叙述的格式如下:
    5 U4 ^+ q- L; ?4 l$ S2 |: X3 gprintf format, item1, item2, .... N; K+ B: }3 H3 F. n
    print 与 printf 的差别是在於 format, printf 的引数比 print5 k7 g' B" J5 F6 u
    多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。
    " X. l& b! n7 K5 R# dprintf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙9 D+ ?8 Z# o; K, m# @4 N$ p
    述没有任何影响。
    2 f4 c$ F) R# N$ M! ~格式的指定以字元'%'开始,後面接著格式控制字母。
    ; t" n7 L3 q' `格式控制字母如下所示:2 r5 h7 ?: R# Q4 p% @& @/ b; U
    'c' 将数字以 ASCII 字元印出。" p' s6 y" U" R4 q% T3 }
    例如'printf "%C",65'会印出字元'A'。
    ; ]* G: q% O8 a1 k' l'd' 印出十进位的整数。! ^+ I0 A) ?$ k, h2 \9 s! y* k
    'i' 印出十进位的整数。
      I( C- T  n' x! N! P'e' 将数字以科学符号的形式印出。
    . j6 N8 O. f/ P5 l8 r: ~例如6 {* K) K' |( J* F) V* n5 f: R
    print "$4.3e",19507 v9 M' a. P; z; @* A+ w. z( P1 |
    结果会印出'1.950e+03'。+ w* K  H* H# m
    'f' 将数字以浮点的形式印出。8 I( n; x/ r. s
    'g' 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果$ M. c% g3 E& M9 Z9 l  v+ G
    大於等於0.0001则以浮点的形式印出,否则以科学符号的形式印
    5 Q+ ]; p7 d' Q' ^9 j出。: h" \- ?& X3 x3 T
    'o' 印出无号的八进位整数。
    8 D5 l9 d; y) ~" K& }, C's' 印出一个字串。; u* x! S  l1 f% B& Y+ u
    'x' 印出无号的十六进位整数。10至15以'a'至'f'表示。+ ?8 }0 Y" l) s% h7 u; b6 i# F
    'X' 印出无号的十六进位整数。10至15以'A'至'F"表示。1 t0 A: ?1 I; I1 a0 [  q0 [2 s  y! y
    '%' 它并不是真正的格式控制字母,'%%"将印出"%'。- D/ f5 ^" g( k/ I# l
    在 % 与格式控制字母之间可加入 modifier,modifier 是用来进一
    " k) f. O/ Q; N# e" |  e3 |; O) P9 F步控制输出的格式。可能的 modifier 如下所示:6 B) J+ C2 G1 O; u+ O
    '-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在
    ' T4 C/ P4 {7 `. H5 u6 ?被指定的宽度向右靠齐。例如:
    2 s7 U* e1 O; t& o, \7 C: Tprintf "%-4S", "foo": B+ U4 |8 N8 p! S+ r. [
    会印出'foo '。
    0 A( {" `3 c! s7 Y' {, S'width' 这一个数字指示相对应的栏位印出时的宽度。例如:% }: x- G2 |+ i$ q3 W4 ?3 p8 L1 s+ j
    printf "%4s","foo"# `! D4 ~/ K, Q' m, z
    会印出' foo'。0 e. s) G9 q, W" J5 K3 T1 U
    width 的值是一个最小宽度而非最大宽度。如果一个 item 的
    8 W4 `1 D$ a. j/ F6 ^( o值需要的宽度比 width 大,则不受 width 的影响。例如+ D8 X- v: \1 a  K6 b* g1 A
    printf "%4s","foobar"$ a& J. B6 C1 ]/ q2 @+ j7 c
    将印出'foobar'。1 s( Y* W* v2 p5 M" ?" V
    '.prec' 此数字指定印出时的精确度。它指定小数点右边的位数。如
    9 l  O3 N3 V! @) f果是要印出一个字串,它指定此字串最多会被印出多少个字
    $ O8 N! S* i; n+ Q& v. _8 r: k元。4 x7 ?' U# M: M0 Z+ r( N. q

    8 F5 Y3 I, i- l8 [8 m( d8 h( R第五章 patterns6 Q1 e( ^2 d4 B1 ^- _7 W% G1 ?& \
    在 gawk 程式里面,当 pattern 符合现在的输入记录(record),其
    . b- T9 k3 u7 {% r8 \: v相对应的 action 才会被执行。
    3 K+ W3 u3 Z* Y
    2 f! H5 H$ F$ @" j$ p5.1 Pattern的种类' k  W; R+ v! ?6 J4 A* M+ w7 v
    这里对 gawk 的各种 pattern 型式作一整理:
    ( u" s6 A7 G$ e! |3 m" R8 e" S/regular expression/
    . J0 Q! ~' \  r5 O一个 regular expression 当作一个 pattern。每当输入记录 (
    3 X. y6 W: @6 Nrecord)含有 regular expression 就视为符合。
    ! ?- e% g' G9 \( Sexpression: L7 p) E5 N- B/ W. F$ m! g8 S
    一个单一的 expression。当一个值不为 0 或一个字串不是空的,2 A: E9 r: i; {
    则可视为符合。
    2 r& x% {2 P$ l1 o- wpat1,pat2  R: Q( ]% F8 b- y# N
    一对的 patterns 以逗号分开,指定记录的□围。; a! H1 i0 o% z0 L' L% x
    BEGIN' x; z$ `- _, r" y" Q4 |% B
    END
    ( e6 P8 L4 q, w2 ]  ?& C, L# w这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相
    " m, X" ~( t8 S2 K3 r对应於BEGIN或END的 action。
    # r0 w1 f& V8 z# Ynull
    " h, H! F- g( Q2 b9 {$ o这是一个空的pattern,对於每个输入记录皆视为符合pattern。4 }0 ]& U; s$ |

    # s) \7 p9 j* ~* y; H, U% L5.2 Regular Expressions当作Patterns
    ; s6 Z' h+ Z, V4 x一个 regular expression 可简写为 regexp,是一种描述字串的方  f0 O: v5 k% x6 G0 ]
    法。一个 regular expression 以斜线('/')包围当作 gawk 的 pattern。/ I  \4 u5 S+ W- W( A3 Q; j# [
    如果输入记录含有 regexp 就视为符合。例如:pattern 为 /foo/,0 V0 q$ m6 |. h, V+ w0 b2 W
    对於任何输入记录含有'foo'则视为符合。
    $ E2 Q9 H% m3 K下面的例子会将含有'foo'的输入记录之第2个栏位印出。7 g4 _; b$ u* _. x
    gawk '/foo/ {print $2}' BBS-list6 C3 X; I! e1 s- I1 @4 p9 ^. E0 |' k
    结果如下:8 ]0 K/ A, i* O& p* G, }' v
    555-1234
    ! R  O5 D* @" S( l555-6699- c4 w. l$ Z. j' O) T! j; X7 W: w
    555-6480) L* K# k& S. z+ q; @) K( j
    555-2127
    2 D& W/ ^- g' w1 V8 N4 Q2 z& zregexp 也能使用在比较的算式。; k, A2 i; W' u3 s8 `
    exp ~ /regexp/$ @, I- R8 j$ S" u% ^0 O( d
    如果 exp 符合 regexp,则结果为真(true)。9 O: ]& Z1 o! o& Y( Q3 a" e! E/ G
    exp !~ /regexp/
    1 x7 J( Z/ J# r5 y5 `7 r* [. E( c如果 exp 不符合 regexp,则结果为真。1 q4 R  t1 c5 Q+ @: G+ B+ k
    8 @/ S- v: a6 ~8 E8 N/ s7 N
    5.3 比较的算式当作Patterns
    + G* `" l% i# Y; ?! L5 ~$ q比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於
    + U# |( u. S# k# m、小於。下面列出一些比较的pattern:
    ( u: W1 g! i7 N8 jx<y 如果 x 小於 y,则结果为真。! \$ J& Z, V* Y& Y) D
    x<=y 如果 x 小於、等於 y,则结果为真。
    * F" g- m$ o2 Ux>y 如果 x 大於 y,则结果为真。
    . z  U, g: l0 b" Z, O* q& q* Ex>=y 如果 x 大於、等於 y,则结果为真。$ c$ @; L2 X8 ~% R# F( @
    x==y 如果 x 等於 y,则结果为真。
    7 [( {+ J' Y' e- ~& zx!=y 如果 x 不等於 y,则结果为真。0 P5 O; ?2 o: @3 @# }1 V
    x~y 如果 x 符合 regular expression y,则结果为真。
    % l. q# m% j) ?- q7 ^' Mx!~y 如果 x 不符合 regular expression y,则结果为真。. @% Z% c% Y3 ?6 K+ G
    上面所提到的 x 与 y,如果二者皆是数字则视为数字之间的比较,
    . l4 X: [2 a6 w, I8 r否则它们会被转换成字串且以字串的形式做比较。两个字串的比较,
    1 J- A. ~/ K1 F' X# P' N5 |会先比较第一个字元,然後比较第二个字元,依此类推,直到有不同) `8 S8 a( u! k/ f; P
    的地方出现为止。如果两个字串在较短的一个结束之前是相等,则视+ b9 d6 I+ _" p) _; m4 _
    为长的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。0 n, ~  m- Z3 S0 t
    $ M9 Z: o! D' ?0 T  ^  }, c
    5.4 使用布林运算的Patterns
    4 \5 t( F# G* R; F, [一个布林(boolean) pattern 是使用布林运算"或"('||'),"及"
    $ o7 b4 l2 B' {1 T$ W('&&'),"反"('!')来组合其它的pattern。
    ! U. \% V6 m& Q& [+ X$ I例如:0 {- m: E. l# p! w: f) S4 X1 K
    gawk '/2400/ && /foo/' BBS-list8 e' O0 n$ e8 V+ L. X* q% Z
    gawk '/2400/ || /foo/' BBS-list
    3 m! `0 H$ X) G; j' Z8 Z4 xgawk '! /foo/' BBS-list
    9 e: q5 y' P$ A7 a; B! m/ ~/ d  V, @3 ~$ r* x3 W! V% t! R
    第六章 算式(Expression)作为Actions的叙述
    3 L. k7 c; Q4 @算式(Expression) 是gawk程式里面action的基本构成者。
    ) J* a, ~  ~& `( B
    & ~/ f% q" l* n) h6.1 算术运算/ O7 Q% X) a- }( X. u1 X
    gawk 里的算术运算如下所示:
    ) S4 P; b* ^5 @; qx+y 加
    : {4 e/ i9 P- W- y2 G: ?1 D) Lx-y 减/ N: M% y: q8 S9 X
    -x 负
    & a) g" E0 \) h/ ^+x 正。实际上没有任何影响。
    8 H; |$ x9 \; q4 Q9 o' jx*y 乘) f) o- r4 |+ Y
    x/y 除4 _# z+ d7 ?4 @% y5 T' B8 ?
    x%y 求馀数。例如 5%3=2。
    # N9 ~1 q! [9 L# Ix^y
    * Y) F6 i# i3 C7 P7 j, ox**y x 的 y 次方。例如2^3=8。1 L, a! Z/ g9 i( |0 m/ T- ~! t" }

    ( @' }4 N( ]: l( |$ @: ?% e6.2 比较算式与布林算式
    ! N# F. }6 p, S5 U3 b8 a比较算式 (comparison expression) 用来比较字串或数字的关系
    ! ]' C* b" `/ N/ D,运算符号与 C 语言相同。表列如下:) |: u8 K; ?, l! U" I
    x<y+ c) Y/ C  b- B1 {. H/ S
    x<=y
    ! k. y0 z; e" bx>y1 \% }3 X2 s- F
    x>=y# C5 g6 y2 P" i
    x==y
    3 G' R# z# |, n0 z8 @x!=y
    $ M9 N3 I# S' Q) f7 [x~y9 F1 b3 I3 d, W& u0 M: U6 ^
    x!~y# K2 Y$ {' ^* M. V
    比较的结果为真(true)则其值是 1。否则其值是 0。
    / w7 f- P0 V1 u布林算式(boolean expression)有下面三种:) Z; i. A3 m1 z" O
    boolean1 && boolean20 {) ~  J3 u. E2 }) B
    boolean1 || boolean2, J4 G  y- O; V$ i
    ! boolean0 q( k: j4 g& f: Y# _: Q" K
    ' l+ S- G) I8 e9 e" P
    6.3 条件算式(Conditional Expressions)
    # ^) a9 D# ]% ^( o+ q# u+ K+ g+ G一个条件式算式是一种特别的算式,它含有3个运算元。
    7 Q) M: I. n/ w条件式算式与C语言的相同:$ Z  O8 }* k+ ^2 {* E3 C3 y  b5 R/ X
    selector ? if-true-exp : if-false-exp: ^1 Z$ e0 p0 o' E* {* U7 v, {
    它有3个子算式。第一个子算式selector 首先会被计算。如果是真,
    ( y$ G7 Z; P+ {( \% N  N+ b则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-+ e8 S, a! k% L; L8 _$ ]/ U- A
    exp 会被计算且它的值变成整个算式的值。
    - m: L" }: C5 ~. _5 Q2 p3 {' k例如下面的例子会产生x的绝对值:
    7 X/ ]! C# A* Z1 f3 ex>0 ? x : -x
    0 x: `% Z: h% u8 E) k
    ; K2 j" J3 b! B第七章 Actions里面的控制叙述) O; I  m4 R6 h$ ]1 S' V3 T
    在 gawk 程式里面,控制叙述诸如 if、while 等控制程式执行的流
    $ L  @9 K4 S( e8 V. V程。在 gawk 里的控制叙述与 C 的类似。
    / D& I( C3 G* h很多的控制叙述会包括其它的叙述,被包括的叙述称为 body。假  d3 Y6 F) j! |1 Q& b
    如 body 里面包括一个以上的叙述,必须以大括弧 { } 将这些叙述括起6 q% j7 {/ [; D' V. N, M/ Z- @! _
    来,而各个叙述之间需以换行(newline)或分号隔开。% j# v0 z: h+ ~$ a7 N

    . ^$ [6 V3 p' F7 S, G' G, [7.1 if 叙述
      g9 S9 ?4 r& F( V& x4 bif (condition) then-body [else else-body]( f( U" h4 S8 H% e) ~7 y' A  O. y
    如果 condition 为真(true),则执行 then-body,否则执行 else-body。8 O! D0 V7 Y! _3 n8 A- u7 o
    举一个例子如下:
    # p8 A2 s, d* M7 I9 iif (x % 2 == 0)
    3 _3 |7 z5 d% _- ]4 t7 |2 G( d+ a4 \print "x is even"
    9 t* R. s7 k, r) w7 r% Helse
    $ J$ b' y( G. I: E* |4 d1 Wprint "x is odd"- S0 h6 w* L/ G

    - o9 W4 Z, C# P  ?  e2 r* \# @5 U7.2 while 叙述$ x- \; b+ W7 ]( q7 A8 q. W" R2 j7 I
    while (condition)
    " Z' k& |- e" Y$ r+ B- U1 Bbody
    + ?& y! Y7 R, H1 W8 {( \) Gwhile 叙述做的第一件事就是测试 condition。假如 condition 为真则* g* m( ^- M* R$ X+ b- Y9 x
    执行 body 的叙述。body 的叙述执行完後,会再测试 condition,假如; ?+ `, [6 v# j' _; o2 p
    condition 为真,则 body 会再度被执行。这个过程会一直被重复直到
    ) W& x3 B5 h9 \' n6 E: m* xcondition 不再是真。如果 condition 第一次测试就是伪(false),则
    : z0 [1 d; }# w+ N( S2 W$ Vbody 从没有被执行。7 ?& E3 S2 U4 E% V1 r- E
    下面的例子会印出每个输入记录(record)的前三个栏位。
    2 p) V5 k: O$ a4 i7 b  ^, N4 a+ f5 kgawk '{ i=1' @  c- X+ W) X# r7 ?6 ?- y" J
    while (i <= 3) {
    0 X. ]. R7 n) a& [' uprint $i
    # p! U4 N0 T- I8 ~, G4 P9 Pi++9 U9 h5 g9 f7 X/ K  ]! h( B- U
    }) `! W' b9 O& G$ y" P& V( `
    }'
    0 }' L# I* s8 o, o
    ' a8 O; A8 O" c" }2 j9 L# m7.3 do-while 叙述
    " Q% {9 _0 x; J. I# E; f" }' Ydo9 Y! I# H. Z2 r& a
    body8 Z9 X3 K, v: i
    while (condition)
    2 V. B0 c: `# m9 m这个 do loop 执行 body 一次,然後只要 condition 是真则会重复执行 body。
    9 l! ~, q* @* B+ v即使开始时 condition 是伪,body 也会被执行一次。
    / [- p' N) R& g6 `6 E下面的例子会印出每个输入记录十次。
    ( j' B2 T  N% _2 t" vgawk '{ i= 1( b4 I* L! w. F7 i* Q. i
    do {
    9 X1 [2 T+ h/ H* ^5 {$ E* {print $0
    0 l8 c6 j3 }5 q& m/ bi++
    ; t- X% X8 d" G4 V! F+ M  W1 t7 `5 ^} while (i <= 10)
    - p* g' s; r& M}': @3 O5 E0 e7 X2 S8 A  X) V1 Z
    7 q# u2 a6 [! x8 ?& m
    7.4 for 叙述
    & \6 S+ J5 h+ ]! S5 Zfor (initialization; condition; increment)
    ) M1 [6 r! I9 gbody' z- |: x2 r2 @0 x0 O
    此叙述开始时会执行initialization,然後只要 condition是真,它3 `- W* |( D6 N
    会重复执行body与做increment 。! `( i! w& C2 r1 y1 m. m
    下面的例子会印出每个输入记录的前三个栏位。4 W6 h) L2 f+ m/ y0 s
    gawk '{ for (i=1; i<=3; i++). b: J& U3 L* Z  Y; Y0 e' T
    print $i
    9 U/ \; k. |( T5 b. `0 ]. K, X* K}'0 h5 T% ?" f4 g* e/ _

    : A) [! E- s) X# h7.5 break 叙述' y# t. N0 }5 U! F
    break 叙述会跳出包含它的 for、while、do-while 回圈的最内层。& z9 n. m8 ]. `. A6 B  b
    下面的例子会找出任何整数的最小除数,它也会判断是否为质数。5 _3 B* t* P3 [
    gawk '# find smallest divisor of num
    ' J2 [" O% A8 E# t, ]& E6 z{ num=$16 `/ a# ~4 K: _. s8 ?+ F
    for (div=2; div*div <=num; div++)
    ( }  S. A9 h* l" r% r5 \if (num % div == 0)
    & o9 h$ ?$ {; w& [break" ?- g6 l- }8 E% ]
    if (num % div == 0)& n( i4 F; ^7 R8 ~, W( D- }
    printf "Smallest divisor of %d is %d\n", num, div
    - T1 K( E9 p/ Q% D, Qelse
    5 I: T: f, t' G, s9 p/ ~printf "%d is prime\n", num }'
    8 W- G- C, _% L
    ( E- W3 {( s# ]4 B' |- T$ O' E+ e7.6 continue 叙述
      u0 t& s$ X9 s* S% _continue 叙述使用於 for、while、do-while 回圈内部,它会跳2 \7 m" ]4 \! P. c4 O* p8 n
    过回圈 body 的剩馀部分,使得它立刻进行下一次回圈的执行。
    ! O4 T7 V* Y+ s9 }9 G' N# h下面的例子会印出 0 至 20 的全部数字,但是 5 并不会被印出。
    - X2 U5 Y$ I7 s/ k9 zgawk 'BEGIN {  ?- w) }8 t1 H3 y/ }2 i
    for (x=0; x<=20; x++) {3 g. t+ B4 Z( \' k& p! N+ f
    if (x==5)
    ' A2 g3 J4 ~( s3 n9 g9 fcontinue
    5 [/ ^' X  L8 l; }! M4 s5 Yprintf ("%d",x). g5 E0 e/ o2 a/ Y8 c& U6 z0 `
    }
    + f; s" ~& \$ }8 f0 a! M4 Sprint "". y: ]+ J$ K4 b  K# D
    }'. Z% [7 C4 x; {7 N. J( ~* z
    ; L& |% h7 a& n8 u" a
    7.7 next 叙述、next file 叙述、exit 叙述4 f  x2 s. ^  m. T6 q) `' m& Y3 E
    next 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一
    5 L5 Q& P& r2 Q& t- _6 ]! \, ~个记录。
    : A" h. M# W2 s2 Z, Y4 E4 lnext file 叙述类似 next。然而,它强迫 gawk 立刻停止处理目前
    / e! m: l% Y# n" C的资料档。
      _# t8 c4 Z4 [' ?0 c; n. Jexit 叙述会使得 gawk 程式停止执行而跳出。然而,如果 END 出现
    & v# K  B9 ?: n. I( U* t,它会去执行 END 的 actions。
    + h3 |7 [0 @! l. ^. f& D3 l7 f4 A1 i2 O! w( c
    第八章 内建函式(Built-in Functions)
    ! l$ c3 m: j% m1 R' G- I' m内建函式是 gawk 内建的函式,可在 gawk 程式的任何地方呼叫内建
      R* m2 L' _! h+ y7 O6 x* e函式。" G: ?$ u" x* T# T1 p6 O
    ; h: R* T! f- F! C6 y
    8.1 数值方面的内建函式
    $ V' {, C+ w1 r5 N$ n% Uint(x) 求出 x 的整数部份,朝向 0 的方向做舍去。例如:int(3.9)
    3 F: [! `6 `+ k! U% T6 E是 3,int(-3.9) 是 -3。
    " W" {* o# a7 v# s  a2 g" J$ o/ Wsqrt(x) 求出 x 正的平方根值。例 sqrt(4)=22 u" q0 C* R& ?9 a# g
    exp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。; W: w+ f8 \( ^) a
    log(x) 求出 x 的自然对数。( D/ l. P4 a& _1 N
    sin(x) 求出 x 的 sine 值,x 是弪度量。! Z7 ], n9 i4 Y. P
    cos(x) 求出 x 的 cosine 值,x 是弪度量。* V- [2 n; T  n, \6 M0 F( H
    atan2(y,x) 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。4 l& B5 T8 b( v3 m+ I& c" U
    rand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个
    ( @) s3 T. T" u* }& t: N值不会是 0,也不会是 1。- W2 ~- e% L- {* Y8 d
    每次执行 gawk,rand 开始产生数字从相同点或 seed。0 H+ e+ X" j  A2 }
    srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设' C& L% ?* P! n: Y5 B. i5 X
    定相同的 seed 值,你将再度得到相同序列的乱数值。
    2 r. P+ }* X3 ]* X. t如果省略引数 x,例如 srand(),则现在的日期、时间会( p/ _. }9 ~) @2 G& Q
    被当成 seed。这个方法可使得乱数值是真正不可预测的。
    " {) L" t0 v3 w: S8 P7 gsrand 的传回值(return value)是前次所设定的 seed 值。4 N9 a) K& P: w% x/ w) X3 t; }. i
    7 n( B& {) U0 l$ t& x+ \9 Y# ]
    8.2 字串方面的内建函式
    : s- l& Y) \! Eindex(in, find), t4 i1 k: s% J* P2 ?5 e( x/ Y4 v
    它会在字串 in 里面,寻找字串 find 第一次出现的地方,传回值是! Z$ ?9 H; E' o0 I8 F  [2 d
    字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字1 ^5 F+ w, j) K: {. z8 ]8 p6 E$ \3 t
    串 find,则传回值为 0。
    5 U  b* ^- B- t6 G/ [+ u/ f例如:
    8 K( r9 s# m: G8 eprint index("peanut","an")& s# r, u. i) N! N7 j
    会印出 3。
    8 q* i+ {+ v+ blength(string)
    7 E% a2 s0 Q& Q2 X/ Z$ a8 H  ~求出 string 有几个字元。3 s- ?4 S4 e! x) s" x( N1 y
    例如:
    / Y; P2 B8 M" P  C) B* Llength("abcde")
    2 u' U; N, U5 m( Z是 5。$ ~  W" F" d% i  P  Z- L
    match(string,regexp)
    + U0 V8 ?, A: z; k* r& c, W5 N: qmatch 函式会在字串 string 里面,寻找符合 regexp 的最长、最靠3 K, l  I6 \) k0 R6 I
    左边的子字串。传回值是 regexp 在 string 的开始位置,即 index
    : Z$ i& g, p0 D' H- Q: O值。" q* x) a% z& s
    match 函式会设定内在变数 RSTART 等於 index,它也会设定内在变
    3 |5 R% r' U/ [# ]5 s数 RLENGTH 等於符合的字元个数。如果不符合,则会设定 RSTART 为3 Z/ Y) j6 k2 G( W  w
    0、RLENGTH 为 -1。! H; Y" M. V8 h4 Y+ e1 O( h
    sprintf(format,expression1,...); Q9 w9 l. J0 S
    举 printf 类似,但是 sprintf 并不印出,而是传回字串。
    3 M" @' ?- L* p& b例如:/ `# o( |& d) P6 C4 m/ Y1 ]
    sprintf("pi = %.2f (approx.)',22/7)- \. x/ U8 I6 }# C
    传回的字串为"pi = 3.14 (approx.)". c7 o+ g  ^. e1 q" o  x" ?
    sub(regexp, replacement,target)
    ; Z' M& G; I5 Q; ^7 X# C1 F在字串 target 里面,寻找符合 regexp 的最长、最靠左边的地方,9 S: `# A- y! a3 l* k: ^! F4 w" v
    以字串 replacement 代替最左边的 regexp。
    ! Z1 l" e# D& ^例如:
    : G9 L% Q1 U) r1 ~$ kstr = "water, water, everywhere"0 S5 _( q2 ?* |4 V3 l5 A
    sub(/at/, "ith",str)
    % Q# m. K# Y3 k3 O! H/ H! W* E结果字串str会变成' m, t  D0 ~. e" Y
    "wither, water, everywhere"" A' C/ J6 Q) A1 r
    gsub(regexp, replacement, target)
    . Y; U9 F- K0 s! l' d- X0 o8 w1 Bgsub 与前面的 sub 类似。在字串 target 里面,寻找符合 regexp 的
    * U3 I: B1 y( S+ }8 u# b所有地方,以字串 replacement 代替所有的 regexp。
    1 L3 |, ^! g8 `* u! M例如:, Y: ^0 B- `5 M/ H% O: ]7 f
    str="water, water, everywhere"
    2 u; `( l- J; z9 Sgsub(/at/, "ith",str)
    . r- Q3 }5 p9 D+ e* E; e( G结果字串str会变成' Y" Q3 W2 n. n) X1 E2 ~) |2 r
    'wither, wither, everywhere"
    , v9 |, t0 R- e: t9 gsubstr(string, start, length)
    $ y$ b  E, i0 h2 E! q传回字串 string 的子字串,这个子字串的长度为 length 个字元,
      {' v9 n; ^, i" J% {% x从第 start 个位置开始。
    : W+ a- @! O; o8 K1 b例如:9 \( `8 ?0 S( m( z3 n, M4 B  ^
    substr("washington",5,3)* d* O$ r  l& l0 U' Z0 d
    传回值为"ing"# X5 l& ?# G0 K
    如果 length 没有出现,则传回的子字串是从第 start 个位置开始
    ) k6 q, }+ @* t* H( x/ W& L至结束。- a$ F: i" _0 e5 N' y. c6 S$ z0 o) K' N
    例如:
    - C* V! a" ?. p) T* ]2 C# x! Esubstr("washington",5)
    " e+ l' c; d4 F传回值为"ington"
    % Y" r; b; }, e, P. `8 Gtolower(string)6 ?" r7 @. g: R3 p0 e) T
    将字串string的大写字母改为小写字母。. h* E* y7 @; @
    例如:. Y9 ]' q& i4 u
    tolower("MiXeD cAsE 123")6 I: [& y+ j2 l
    传回值为"mixed case 123"
    7 p  f2 q: Q2 b2 V7 \$ ^/ \toupper(string)
    + Z' s8 S( M  E) e1 |5 R将字串string的小写字母改为大写字母。
    8 m3 Q# B! E1 O$ \9 B/ h例如:$ B$ B9 [$ {7 A; K
    toupper("MiXeD cAsE 123")" U& _( m7 h9 \3 q0 Z
    传回值为"MIXED CASE 123"
    + X5 T3 I; g% G5 s6 P7 ^
    * c- g" w/ ~# B2 ~; n3 Z; ^8.3 输入输出的内建函式
    ; w5 T; j! b5 qclose(filename); }1 N5 H% ]9 u) n) q5 k1 ]
    将输入或输出的档案 filename 关闭。
    2 n0 x' j( N3 E4 {9 r+ |" hsystem(command)
    3 o9 q, y; T: y5 U, A此函式允许使用者执行作业系统的指令,执行完毕後将回到 gawk: Q* x3 R7 L" L2 f9 ~$ M
    程式。) \0 n6 w$ z1 T1 S
    例如:
    - P2 \1 y2 f! g, o1 W3 A7 c# a+ gBEGIN {system("ls")}
    2 j1 I2 V6 H' N1 p4 g- w
    # m! }. @. ~- g" ^: K  i第九章 使用者定义的函式(User-defined Functions)1 Y4 f* @5 V+ l0 r1 a' U
    复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用$ G6 Q" j. x) G5 w4 O" S1 x
    者定义的函式与呼叫内建函式的方法一样。
    $ D+ d! L3 _6 q1 H# ]0 i
      k% o" k, G3 p( h; ?9.1 函式定义的格式, ~* i5 M: ]! B. @) z0 K0 n  H
    函式的定义可以放在 gawk 程式的任何地方。
    0 J# C. L% z" M, h4 O( x一个使用者定义的函式其格式如下:4 Y* w1 U  W4 S( K5 R- n
    function name (parameter-list) {) @  F: z' w  d! |
    body-of-function( }/ U/ V1 N0 }5 q9 A; q
    }
    2 a" `3 r# w% Dname 是所定义的函式之名称。一个正确的函式名称可包括一序列的字
    % U% l2 u# X0 ~$ e$ f: a母、数字、下标线 (underscores),但是不可用数字做开头。
    5 v9 @% r7 Y3 h" I, v; Qparameter-list 是列出函式的全部引数(argument),各个引数之0 ~; `" L  x$ z+ c
    间以逗点隔开。
    ; B* }+ s# G7 E, h. o) ~) `1 Bbody-of-function 包含 gawk 的叙述 (statement)。它是函式定义  l7 Q+ s) f5 Y3 k# ~
    里最重要的部份,它决定函式实际要做何种事。  L3 f8 n9 k: g. V
    ' f9 S3 z3 }0 B( U* Q! m8 _
    9.2 函式定义的例子
    2 G4 ~2 J' j( M% ^9 K; G下面这个例子,会将每个记录的第一个栏位之值的平方与第二个
    0 ^5 H: u( D( r$ r栏位之值的平方加起来。5 w. C0 D9 @5 X6 A: U
    {print "sum =",SquareSum($1,$2)}
    ) P9 O- v9 z( K3 n* t2 t% O6 Ufunction SquareSum(x,y) {4 E- ?; r: q- y, D9 t
    sum=x*x+y*y& T7 K' P# H: f' J$ U
    return sum, r8 g& Z( v; l4 k" _5 B
    }5 L. G6 c) L6 {; _. Q0 S

    ' R5 o6 `; I- M2 X& l第十章 □例; d1 _, W* I+ H  ]  v" c4 E. ~( h
    这里将列出 gawk 程式的一些例子。
    " G( |, [6 X8 N( D/ X* B1 k) M: Xgawk '{if (NF > max) max = NF}; N9 {* ?, b- G3 C- a* K$ U
    END {print max}'+ x7 [. `; T1 }) o6 b/ t7 U
    此程式会印出所有输入行之中,栏位的最大个数。: Y" {; ]% V  ]
    gawk 'length($0) > 80'+ u; `0 P% Y9 d# F: _
    此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被- a( M/ A0 g5 F# M- P* ^
    列出,action 是采用内定的 print。3 q- @0 U: \$ @7 l
    gawk 'NF > 0'
    6 a& v6 K' i6 y) `7 j# S$ Q对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简
    4 S* N1 F0 |# R0 k; b1 N单的方法,将一个档案里的所有空白行删除。
    3 O: E+ @8 k$ b6 Y  \. Wgawk '{if (NF > 0) print}'
    4 t% b  W4 f4 |4 ?' `4 D/ W对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简6 n# ~: d: d6 G& L* S. Z" ~% N  Y
    单的方法,将一个档案里的所有空白行删除。  {- z& q2 f& S' X9 V5 z
    gawk 'BEGIN {for (i = 1; i <= 7; i++)
    # T# ~; S7 g, B3 w9 E$ \print int(101 * rand())}'
    ! ^: j7 H1 ]1 v( i7 q此程式会印出□围是 0 到 100 之间的 7 个乱数值。' s* `! ~1 H$ }
    ls -l files | gawk '{x += $4}; END {print "total bytes: " x}'; Q6 d& @5 `+ ?/ K' E
    此程式会印出所有指定的档案之bytes数目的总和。
    0 H. g9 D- k' l$ I# K! k! Dexpand file | gawk '{if (x < length()) x = length()}  s" X* J5 ?9 T) N4 S) x8 V
    END {print "maximum line length is " x}'
    # E2 F3 y. b! N' P' e5 {此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改
    7 i0 Q) R: b1 S1 H9 q- V成 space,所以是用实际的右边界来做长度的比较。7 a/ D8 B* L' b) Q9 |
    gawk 'BEGIN {FS = ":"}
    5 A' s+ l% i! m* C7 L9 }{print $1 | "sort"}' /etc/passwd
    7 Y% Q' E  |1 h6 @% V5 K, x此程式会将所有使用者的login名称,依照字母的顺序印出。
    " r; s& E7 t/ Z- d+ D" G+ bgawk '{nlines++}) `8 x5 @' f) j  r; t3 D
    END {print nlines}'
    & H% P# X. k8 t: O此程式会将一个档案的总行数印出。) v+ a  q9 G  i0 ^; \, F
    gawk 'END {print NR}'
    8 y8 p8 c# j5 n0 x: ~此程式也会将一个档案的总行数印出,但是计算行数的工作由gawk- h, G9 H; z1 V2 h/ a: |; t
    来做。
    . T5 v- \! Z3 a2 Pgawk '{print NR,$0}'- U* K& u# }2 i0 o; O' W/ k# e
    此程式印出档案的内容时,会在每行的最前面印出行号,它的功
    + T+ {8 C# C, R能与 'cat -n' 类似。
    9 [6 x  s0 {% r
    * j! L' L1 f3 O& t第十一章 结论
    0 ]* d" n2 l  [% F) k* igawk 对於资料的处理具有很强的功能。它能够以很短的程式完成
    4 x. C3 p! W' X3 c想要做的事,甚至一或二行的程式就能完成指定的工作。同样的一件
    % o/ o9 C5 X3 D, N# F工作,以 gawk 程式来写会比用其它程式语言来写短很多。
    : I, P8 a" ^: |gawk 是 GNU 所做的 awk,它是公众软体(Public Domain) 可免费使. U" p" ?( K) ?  N
    用。
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    楼主热帖

    相关帖子

    帖文化:【文明发帖 和谐互动】 社区精神:【创新、交流、互助、共享】

    该用户从未签到

    尚未签到

    发表于 2008-6-12 18:18:47 | 显示全部楼层
    "gawk 对於资料的处理具有很强的功能"
    , @# v# F+ @# G还是不太懂,是一个文本文件的批量处理工具吗?
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    帖文化:【文明发帖 和谐互动】 社区精神:【创新、交流、互助、共享】
    您需要登录后才可以回帖 登录 | 立即加入

    本版积分规则

    招聘斑竹

    小黑屋|手机版|APP下载(beta)|Archiver|电力研学网 ( 赣ICP备12000811号-1|赣公网安备36040302000210号 )|网站地图

    GMT+8, 2026-3-18 04:41

    Powered by Discuz! X3.5 Licensed

    © 2001-2025 Discuz! Team.

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