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

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

Gawk手册

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

    连续签到: 1 天

    [LV.1]初来乍到

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

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

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

    ×
    GAWK
    2 ?; h/ c* N1 s0 \# t9 Y/ q第一章 前言, |+ m  O$ Z' C/ n1 p
    第二章 简介4 Y- Q) V7 u5 T3 S4 `
    第三章 读取输入档案
    $ q3 K$ o9 J4 A9 \7 z2 P) K第四章 印出
    ; J0 X& l! i$ q$ G$ B- P第五章 Patterns# i+ P  A2 W, `7 b- a2 |/ m
    第六章 算式(Expression)作为Actions的叙述- ^/ p5 ~2 T! R( d& @, w
    第七章 Actions里面的控制叙述4 U! l  R/ f8 N! ]2 I
    第八章 内建函式(Built-in Functions)
    , s/ a" A3 W, w/ u; F8 J, F& b第九章 使用者定义的函式
    8 \. Y/ ]) p- |) n6 x, v. Q第十章 □例! P# s4 u- p) m- J
    第十一章 结论
    ( g! t5 Q( n; V1 o- o
    5 i7 I2 d& T" K# B* x9 L=======================================: Y' i; O8 A1 V! h  T0 y
    第一章 前言7 s6 f2 m0 t; c& C3 |0 }0 _3 q
    awk 是一个程式语言,对於资料的处理具有很强的功能。对於文5 z$ i; r: [' e( ~5 R) I2 u
    字档里的资料做修改、比对、抽取等的处理,awk 能够以很短的程式& G3 s* q) }! x  A9 |. t) w
    轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作,
    3 \/ ^$ z( e4 b1 q会不方便且很花费时间,所写的程式也会很大。
    / ?( u$ I% u; `awk 能够依照使用者的定义格式来分解输入资料,也可依照使用2 i. h" u, n' i, Z7 @
    者定义的格式来印出资料。
    ' R% K3 Y, G1 U9 i. {awk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名- n1 h* j" J+ g( p& V2 J9 q. B) W
    :Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。
    8 E6 V3 T2 i2 _* iawk最初在1977年完成。一个新版本的awk在1985年被发表,它的功能
    5 l) C+ _. W# U+ s( P比旧版本增强不少。5 ?5 `: M6 d/ u3 s. k8 X
    gawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不断地; [9 J" @' ?7 P3 J$ s
    被改进、更新。gawk 包含 awk 的所有功能。0 m6 v2 r: ]2 w6 _9 t6 Y) h
    往後的 gawk 将以下面的2个输入档案来做例子说明。
    , A5 u4 V* D5 ^% i- i- F档案'BBS-list':" v" L! f! y: V
    aardvark 555-5553 1200/300 B$ o2 d7 z: r1 Q6 ^' m( j/ t5 u4 o" Z
    alpo-net 555-3412 2400/1200/300 A6 W2 Y/ ]! D/ @3 G' \3 P
    barfly 555-7685 1200/300 A
    ; ]) x/ ]4 a* e* Y# @; Cbites 555-1675 2400/1200/300 A
    3 k% q! x5 r7 U- x: icamelot 555-0542 300 C+ E( i1 H0 ]/ O4 S
    core 555-2912 1200/300 C
    / I8 W/ \0 Q# [2 lfooey 555-1234 2400/1200/300 B
    : o$ P! ^$ `; h' U* Vfoot 555-6699 1200/300 B# N; D5 ?. S' t" @
    macfoo 555-6480 1200/300 A
    0 k; O$ ~7 T4 nsdace 555-3430 2400/1200/300 A
    # Q* v: n( g( G  _3 I1 O# csabafoo 555-2127 1200/300 C
    7 W! i" ?6 e# H  u+ [档案'shipped':
    + |  h; k0 l! D* n7 FJan 13 25 15 115
      r! M1 P, o: h. G- sFeb 15 32 24 2265 H$ a9 o: Z" o
    Mar 15 24 34 228
    0 z5 N1 H: p1 WApr 31 52 63 420
    . D- L7 x! S' {9 B" d. O! [  tMay 16 34 29 208
    + f2 O8 j, w9 O; s! R) dJun 31 42 75 492
    & o8 d* n8 m! S0 d) ^6 L; Y" jJul 24 34 67 4369 i$ q- L/ Z" V. E6 q% g* P
    Aug 15 34 47 316
    * V" C$ o0 Z% q2 r& ^6 ESep 13 55 37 277! @) V- W7 `5 Z; v
    Oct 29 54 68 5254 P! E) r3 u) O
    Nov 20 87 82 577- v2 Y: _/ N7 D& Z) ~3 \- Q
    Dec 17 35 61 401; O7 D1 n  m( \& F7 f5 |" @
    Jan 21 36 64 620
    ' N% a$ H" t6 f9 i: h  XFeb 26 58 80 652
    7 Y) C$ O3 y# u1 S* m/ S- }Mar 24 75 70 495" c5 a5 f  ?% ?
    Apr 21 70 74 514
    + N$ O& \0 s2 s
    # M1 `( {9 H, B. K+ w第二章 简介- S) _4 h# p- i$ q7 N, x' o  G/ M
    gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns' a7 z4 w- s$ j# y
    。当一行里有符合指定的 patterns,gawk 就会在此一行执行被指定
    5 d4 G+ O5 Y% r1 E0 H" {" [的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结8 V5 R# B/ B  R" \* G, J( K
    束。
    ( f$ n+ x# d- n. @0 ?% u  v8 ~gawk 程式是由很多的 pattern 与 action 所组成,action 写在+ D) P/ b: m  |# O5 l; R
    大括号 { } 里面,一个pattern後面就跟著一个action。整个 gawk 程7 B0 B5 L7 s5 B. R0 D7 n) Z7 W
    式会像下面的样子:
    ( c" `- d( [, }, ?( Kpattern {action}
    / V1 \0 E+ N; Xpattern {action}
      k8 R( k. f9 @* T  j! G在 gawk 程式里面的规则,pattern 或 action 能够被省略,但1 A: Q2 a( s- Y/ q* k' [! g! \
    是两个不能同时被省略。如果 pattern 被省略,对於输入档里面的& G- x. K/ T, X
    每一行,action 都会被执行。如果 action 被省略,内定的 action
    4 e& ?+ b7 x& @% a% i则会印出所有符合 pattern 的输入行。4 K4 G' ^6 ~+ x

    - F1 }$ U7 x6 C% ?, V2.1 如何执行gawk程式
    % v( X- x) L$ D5 B0 @; i5 u基本上,有2个方法可以执行gawk程式。) Z# s/ H/ l" }2 Q$ g/ b  `6 I
    □如果 gawk 程式很短,则 gawk 可以直接写在 command line,如下所示:; W0 S7 R: ^# C; s; ~
    gawk 'program' input-file1 input-file2 ...% z* l( R6 w0 Q7 Z" m
    其中 program 包括一些 pattern 和 action。
    2 F2 p$ i& Z6 t7 ]* R5 v, J□如果 gawk 程式较长,较为方便的做法是将 gawk 程式存在一个档案,/ S& D3 \$ ]2 V" d
    即 patterns 与 actions 写在档名为 program-file 的档案里面,执行% ]) [7 V  H( G1 M& }6 r8 _/ I
    gawk 的格式如下所示:, j( o8 L1 B1 ?7 A( `/ D
    gawk -f program-file input-file1 input-file2 ...+ }- k$ z$ R7 z$ g; @
    gawk 程式的档案不止一个时,执行gawk 的格式如下所示:
    : K6 {  s, @( {! z* U' Ugawk -f program-file1 -f program-file2 ... input-file1& y5 ^! g' @( b, h
    input-file2 ...5 {5 W* i# d2 V! j3 a

    " |; k7 B4 Z2 z/ D9 R% T( G2.2 一个简单的例子
    + O: Y% e( j  z/ M1 k3 ~现在我们举一个简单的例子,因为 gawk 程式很短,所以将 gawk 程
    & I2 I) o3 P2 B( j0 z! e  ?式直接写在 command line。: _- n5 s+ u( M3 ]
    gawk '/foo/ {print $0}' BBS-list
    " z' P9 p3 s$ [" {实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern,意思为搜1 O6 T+ P1 y' b$ _" i/ ?: K
    寻输入档里的每一行是否含有子字串 'foo',如果含有 'foo' 则执行 action。
    % }4 k, u0 l0 ]) g1 u3 w% _5 F1 Y. Naction 为 print $0,是将现在这一行的内容印出。BBS-list 是输入的档案。: n* M; m) q. m. {9 d
    执行完上述指令後,会印出下面的结果:
    6 d# P5 o' M# z5 ffooey 555-1234 2400/1200/300 B5 f& a4 M1 T/ p: E; L8 |- q4 v
    foot 555-6699 1200/300 B( d7 |! `7 @9 v
    macfoo 555-6480 1200/300 A/ O) ]- l: r3 O/ d% @2 s4 m
    sabafoo 555-2127 1200/300 C3 W( g( z7 ]+ Z0 E

    . X! ?. s* t7 E5 x0 z& X2.3 一个较复杂的例子
    ! o8 V* n( \3 i$ {' k" L, @gawk '$1 == "Feb" {sum=$2+$3} END {print sum}' shipped
    ) w1 e7 [+ d$ J8 T+ }现在这个例子会将输入档 'shipped' 的第一个栏位与 "Feb" 做比较# T- W5 _5 r' }2 v; Q5 x
    ,如果相等,则其对应的第2栏位与第3栏位的值会被加到变数 sum。
    , d: i5 \/ m2 n3 m' C( {  ~9 |对於输入档的每一行重复上述的动作,直到输入档的每一行都被处理
    : E( i7 A7 V, t过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输
    % S& L+ n$ R: H. y入读完之後,执行一次 print sum 的动作,也就是把 sum 的值印出。
    , H8 u0 t  p2 Q  i0 t' M9 u: N下面是执行的结果:' ?7 _) l! ?8 H# _4 U! v5 }6 g2 i
    84
    " \+ a: k4 u7 K. V7 k9 d, ~$ T* n9 ^* O# C+ a; }; L
    第三章 读取输入档案
    ( n- `) e# z; L0 a6 c+ Y( Cgawk的输入可以从标准输入或指定的档案里读取。输入的读取单
    - I6 T7 |* G$ O; l- i2 ~/ _# o) Z0 S位被称为”记录”(records),gawk 在做处理时,是一个记录一个记# g% I; e9 I' {8 k( {- N6 a
    录地处理。每个记录的内定值是一行(line),一个记录又被分为多个: @$ ~# Q7 b7 n2 S
    栏位(fields)。8 p9 O( K" S! n' V
    * x5 T1 g9 Q9 L: A0 S% O0 w+ i& q
    3.1 如何将输入分解成记录(records)9 u2 j5 [9 u/ f  ~% _
    gawk 语言会把输入分解成记录(record)。记录与记录之间是以4 j; `: h# L: ?
    record separator 隔开,record separator 的内定值是表示新一行的1 G. m- n$ T' v, k$ k9 |
    字元(newline character),因此内定的 record separator 使得文字; s( T% q' z4 t8 D9 T0 ]
    的每一行是一个记录。0 |0 q" L' i6 F& y+ p5 W5 A1 d( j
    record separator 随著内建变数 RS 的改变而改变。RS 是一个字串,$ h% D1 L$ R& K
    它的内定值是"\n"。仅有 RS 的第一个字元是有效的,它被当作 record& B0 a" h0 w, E; ^' }
    separator,而 RS 的其它字元会被忽略。
    " {. K! s. D; L6 O内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内
    : y2 m& r; u! B7 b2 G* z建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。
    ; h5 {$ N2 y: r; O2 w9 G5 p& b$ V
    3.2 栏位(field)7 o" U* w  m; D. `
    gawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一
    + ^% F; y  W* }$ P行里面,gawk 的内定动作会认为栏位之间是以 whitespace 分开。在1 X2 e4 I/ ?) c: a
    gawk 里,whitespace 的意思是一个或多个空白或 tabs。" W& C3 V: L' V9 b% i6 G$ @
    在 gawk 程式里面,以'$1'表示第一个栏位,'$2'表示第二个栏位9 e( _/ a  _; n  \0 b9 L# r
    ,依此类推。举个例子,假设输入的一行如下所示:+ E' m& F3 L  |2 }
    This seems like a pretty nice example.
    ' E/ P8 S% i! F- Y1 `第一个栏位或 $1 是'This',第二个栏位或 $2 是 'seems',依此类推。$ W" M3 N. U' U7 B0 B4 h  @
    有个地方值得特别注意,第七个栏位或 $7 是'example.'而非'example'。
    # T* ~+ f% x( ~不论有多少栏位,$NF 可用来表示一个记录的最後一个栏位。以
    . F9 Z$ a/ @* A; I1 {* m2 H上面的例子为例,$NF 与 $7 相同,也就是'example.'。
    $ z: b* k* k. q, A) ZNF 是一个内建变数,它的值表示目前这个记录之栏位的个数。1 P/ z( y: ~4 O# S, a% J* w
    $0,看起来好像是第零个栏位,它是一个特例,它表示整个记录。
    " u" Q2 o4 ^! z  v; c3 E2 X# X下面是一个较复杂的例子:
    ( X$ f+ L- C* b0 u2 Agawk '$1~/foo/ {print $0}' BBS-list
    + o, I; l: s* p9 y8 {4 F结果如下:
    ; c9 e. Q' ~% Q# U5 }* xfooey 555-1234 2400/1200/300 B
    , k* z- ?9 U7 V( lfoot 555-6699 1200/300 B
    $ N) }4 J) G5 y5 D' K. X0 Imacfoo 555-6480 1200/300 A
    # ~+ B1 }. N0 D  i. O8 nsabafoo 555-2127 1200/300 C
    1 \7 V% k( h2 C9 U: X, c这个例子是把输入档'BBS-list'的每个记录的第一个栏位作检查,如
    + k8 _' U* T& G6 c果它含有子字串'foo',则这一个记录会被印出。
    ; r: Y: a& j6 x9 f- a  k7 P# I" f
    3.3 如何将记录分解成栏位
    $ r/ E3 `% U* Z( ~5 [gawk 根据 field separator 将一个记录分解成栏位。field sepa-
    , K( J, R( z; J/ |9 q0 Lrator 以内建变数 FS 表示。
    ! }5 z, H0 p1 n5 c* h举个例子,假如 field separator 是'oo',则下面的行:
    / F. |( o! Z! V9 [8 hmoo goo gai pan
    ) i) ~/ F' V) g1 K7 z5 k会被分成三个栏位:'m'、' g'、' gai pan'。
    & S" d7 c; g& M  ?在 gawk 程式里,可以使用'='来改变 FS 的值。例如:) {4 m5 M$ F- r0 q) P5 Z! h0 F
    gawk 'BEGIN {FS=","}; {print $2}'! Z6 I* [4 d) S2 d. Q
    输入行如下:
    3 D7 c% S8 v+ ?/ l, a5 e, \3 TJohn Q. Smith, 29 Oak St., Walamazoo, MI 42139. J& U( z3 K# C- T: m- F
    执行gawk的结果将印出字串 ' 29 Oak St.'。BEGIN 後面的 action 会在
    2 Z; D4 C, c9 Q- D, ^( j第一个记录被读取之前执行一次。
    8 l4 z* \5 q, M5 N2 L7 I1 |4 }
    ) ^# ?. A3 ]' I3 @7 \% s第四章 印出! y' V  l  l# Q4 @/ o2 @8 q
    在gawk程式里,actions 最常做的事就是印出(printing)。简单* p# h) T" x! y( w7 s% g, ~% K
    的印出,使用 printe叙述。复杂格式的印出,使用 printf 叙述。
    4 X0 ?! k- f8 `# d% n
    / ~" [. Z2 F7 \. \1 T; H& ?4.1 print叙述
    7 W& w/ P  I0 u6 U! d6 I2 t4 eprint 叙述用在简单、标准的输出格式。叙述的格式如下所示:. i$ A6 l% g6 @; g& a
    print item1, item2, ...$ R  Z& D. Q% f% f' m6 F% I! l
    输出时,各个 item 之间会以一个空白分开,最後会换行(newline)。+ m/ ?5 V) E  S" `4 @  C5 E
    如果 'print'叙述之後没有跟著任何东西,它与'print $0'的效
    ! m$ J9 U4 W2 Z3 o果一样,它会印出现在的记录(record)。要印出空白行可使用'print
    . [  n6 K6 U. E5 V% K""'。 印出一段固定的文字,可用双引号将文字的两边括起来,例如
    - s" E! p8 {' S4 r'print "Hello there"'。0 ~2 q' B$ I1 Z% G& L
    这里是一个例子,它会把每个输入记录的前二个栏位印出:
    . N8 g2 I) o. ~gawk '{print $1,$2}' shipped
    3 Z# g  @* s1 h结果如下所示:
    9 D, Z  r5 I$ `' P% jJan 13
    3 |1 z( f& Z; K" mFeb 15
    3 [) K! e; ?3 b' U/ @: q& ]( _7 rMar 153 S$ t. X7 H7 N' ~
    Apr 31: |& {  h' m1 e  e. C5 t
    May 16
      u1 @; i( a4 j3 {  R/ l4 hJun 31
    ) f3 t$ j, T4 F4 b2 F0 wJul 24
    7 C( _) n$ I4 h7 m  |' VAug 15% m% |5 \) q) w# C( X1 @
    Sep 13* Q1 H, L5 c* l7 |5 R. y
    Oct 292 Y& p2 v7 z& ^: Y( V6 k
    Nov 20+ T  q# {4 B/ @3 }2 ]
    Dec 177 N9 B2 f, i" a' E' e
    Jan 21
    ' o# s0 S- F* V9 o0 vFeb 26+ J4 H' ?" b" J5 N8 I$ R; V* I$ `% ?
    Mar 24" i4 \/ Z/ g8 L5 r/ k& ~
    Apr 21  G) l. [0 y8 @& v- g2 s, M# [

    4 Q# H4 c/ z2 Z# t% \( _7 k4.2 Output Separators( F# }) C0 V4 Z0 M
    前面我们已提过如果 print 叙述包含有多个 item,item 之间. T: M2 O+ q0 p. N- h
    用逗点分开,则印出时各个item会被一个空白隔开。你能够使用任何2 W+ y+ d0 d7 X5 j% a( V0 O; p1 b0 T
    的字串作为 output field separator,可以经由内建变数 OFS 的设
    * Y* P* i/ _/ U2 o定来更改 output field separator。OFS 的初始值为" ",即一格的
    - K$ l1 [: N; S4 P; C0 y空白。1 C" [; C5 a$ ~- `
    整个 print 叙述的输出被称为 output record。print 叙述输
    9 H* d* x6 T; h3 e出 output record 之後,会接著输出一个字串,此字串称为 output
    9 w5 z' d- x- L* Grecord separator。内建变数 ORS 用来指明此字串。ORS 的初始值
    * b- J7 Q! w8 w# Q5 i为 "\n",也就是换行。; Y0 F  I- p! \
    下面这个例子会印出每个记录的第一个栏位和第二个栏位,此二9 B4 j' ?. N- ^0 ^/ n
    个栏位之间以分号';'分开,每行输出之後会加入一个空白行。
    / z/ o( W& ^9 v* U% O) y3 Sgawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list
    / _- ?5 M2 `5 n" b+ u& k% h结果如下所示:
    ' {# g$ S3 f! g; L8 R6 @2 O0 @aardvark;555-5553
    % V, y9 T9 A9 b; f8 _& ?alpo-net;555-34124 g( T8 n6 V& T0 n! T
    barfly;555-7685
    & M4 v: C9 D2 e6 ?, I( Bbites;555-1675
    & c8 T- N: L: x8 b' S6 @4 Z% xcamelot;555-0542
    + f' G+ Y6 M" Ucore;555-29123 j) x3 O6 ~* x, O8 x( Q
    fooey;555-1234
    " D0 C& o2 l: D8 d' {3 ~/ E/ xfoot;555-66993 j" Y- d2 q) G, r6 G
    macfoo;555-6480$ b" ~: I% U# ?2 R  s
    sdace;555-3430
    8 l# X0 u- M) d7 Q/ t' tsabafoo;555-21273 q6 p% `" Q, I$ |+ G6 R! O; t
    1 m/ P  Q9 n. w: S
    4.3 printf叙述
    ( {0 T. _1 a1 h; E& n% K/ Z2 Lprintf 叙述会使得输出格式较容易精确地控制。printf 叙述可以* W- H* Y8 y% _
    指定每个 item 印出的宽度,也可以指定数字的各种型式。
    , l/ `, `8 I$ O+ b' m9 Nprintf 叙述的格式如下:
    ! R; b+ V! p: o5 G# T3 z0 Lprintf format, item1, item2, ...' o" |2 I. J( Z" }! x
    print 与 printf 的差别是在於 format, printf 的引数比 print
    8 f) i6 f7 b: I* x0 G" {$ T7 Q5 `多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。6 C/ P; S2 ~, @7 E9 N/ h
    printf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙+ s# O1 s2 L, b- s
    述没有任何影响。4 g  P$ r4 c5 P# u# i
    格式的指定以字元'%'开始,後面接著格式控制字母。! D' Q8 C5 G( V) V& V  d8 t# x
    格式控制字母如下所示:
    ; e& d' V- C( H  J. x'c' 将数字以 ASCII 字元印出。
      k! X3 d; u9 W6 |+ S8 m/ u( Y例如'printf "%C",65'会印出字元'A'。& N/ I( Z# p+ R8 H/ V# d
    'd' 印出十进位的整数。- i0 C$ z( X' f7 T5 G8 ]( k
    'i' 印出十进位的整数。, H: @) s& q2 U, Z8 t5 T
    'e' 将数字以科学符号的形式印出。8 r6 k: }9 F* A  j. K+ ]
    例如1 l' }+ I$ a& V0 o
    print "$4.3e",1950
      x: Y& {3 o/ n8 L; o6 w结果会印出'1.950e+03'。
    3 w2 A7 `% `( _! H, G9 o'f' 将数字以浮点的形式印出。1 M3 p$ o0 L  R: k2 P
    'g' 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果/ X6 u" ]% t) L" c
    大於等於0.0001则以浮点的形式印出,否则以科学符号的形式印
    8 D( Q* e2 m, _出。, u$ e/ h& k: ^# K# n
    'o' 印出无号的八进位整数。
    # A0 d+ w& c  D's' 印出一个字串。
    6 I6 @( x2 [) i  C: p# c6 l'x' 印出无号的十六进位整数。10至15以'a'至'f'表示。
    ; Y, R0 g2 S$ }) q'X' 印出无号的十六进位整数。10至15以'A'至'F"表示。# ^. i: F0 K! s: l$ e3 ^6 a* @
    '%' 它并不是真正的格式控制字母,'%%"将印出"%'。. J7 _% `' h' v+ z9 `4 y8 _/ q
    在 % 与格式控制字母之间可加入 modifier,modifier 是用来进一& k4 R( N- M6 t8 _( S/ {/ z
    步控制输出的格式。可能的 modifier 如下所示:
    & O; ^5 C% M1 A( Q' Y- n0 D; C'-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在( u; |- |; O. |' l
    被指定的宽度向右靠齐。例如:5 r7 A& {' L; p& a( N
    printf "%-4S", "foo"0 e9 r! ^- O# p7 O9 |( ~1 `
    会印出'foo '。
    6 x( H* U" R; M5 [) g! `'width' 这一个数字指示相对应的栏位印出时的宽度。例如:
    1 s+ |5 q3 V( e  H) tprintf "%4s","foo"
    & T9 }* x) o) `  ~8 ^+ W: S会印出' foo'。( ]# @. g- [6 q' G5 _* y- D
    width 的值是一个最小宽度而非最大宽度。如果一个 item 的
    * X9 ^. `( Z. k. ^' e, O! g值需要的宽度比 width 大,则不受 width 的影响。例如7 P3 l: J' P6 l- v
    printf "%4s","foobar"
    - u( r+ ^" O) Z7 p: ~将印出'foobar'。$ @  {& h1 d$ H
    '.prec' 此数字指定印出时的精确度。它指定小数点右边的位数。如  j0 c' V" @, R
    果是要印出一个字串,它指定此字串最多会被印出多少个字
    3 ]1 c) e& i+ B  |元。# `! ^+ f3 U6 ]6 P- q

    ! }* u% C" k/ X3 v- z2 {! A& q第五章 patterns
    7 Z* U, U9 B  n. m在 gawk 程式里面,当 pattern 符合现在的输入记录(record),其" C( ]; x" e' ?9 `
    相对应的 action 才会被执行。% p" ]: J3 Y9 C% I' p
    5 P( B, \) O( K: i
    5.1 Pattern的种类9 N  x% z% {. K2 s. z& x
    这里对 gawk 的各种 pattern 型式作一整理:
    : z3 E) l5 n  W/ J) @( C6 D/regular expression/
    + c' g. ?9 W4 G7 R( h& L" V' r& _* L一个 regular expression 当作一个 pattern。每当输入记录 (2 R: I; n' N# U; {0 v1 F4 v
    record)含有 regular expression 就视为符合。4 a  M6 K  I0 P
    expression* l# r- D+ p% A& X. t
    一个单一的 expression。当一个值不为 0 或一个字串不是空的,
    % \* i* [* b: s8 h) B& ~5 r+ c则可视为符合。
    . k2 j& j$ l1 ]1 E1 Bpat1,pat2: Q) A2 Q; H" k& K6 r  M7 L
    一对的 patterns 以逗号分开,指定记录的□围。2 d5 l+ t& F9 n+ Y# d- M6 F
    BEGIN
    ) k# E3 r. i7 V- v, N' k, l/ f: aEND4 [. f: I4 N  M% t" A5 Z" J2 }
    这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相& P7 l5 h) A3 Z, ^1 O
    对应於BEGIN或END的 action。
    0 l( r6 w4 G3 O0 z& Ynull
    # F% W; B$ h: q# Y# `! Y/ m$ L这是一个空的pattern,对於每个输入记录皆视为符合pattern。
    & N- C( U7 \  ]& F9 Y# Q( P/ F9 i+ k0 X2 u9 [# u
    5.2 Regular Expressions当作Patterns! g  Y( e7 ]/ F
    一个 regular expression 可简写为 regexp,是一种描述字串的方* q7 ]) C0 b, L, k% [9 v
    法。一个 regular expression 以斜线('/')包围当作 gawk 的 pattern。* f) `: d: {  i& n, A
    如果输入记录含有 regexp 就视为符合。例如:pattern 为 /foo/,
    ; w! @; e+ H+ u) c( t& f5 _- J对於任何输入记录含有'foo'则视为符合。
    3 j5 C" C# D% i2 z, G$ N下面的例子会将含有'foo'的输入记录之第2个栏位印出。; d- K, L& @! }7 r5 T' v6 C, y: k
    gawk '/foo/ {print $2}' BBS-list% {3 [% c( o0 L* U
    结果如下:2 r: O# d1 i! ?7 |1 M% `
    555-1234# H1 ^$ c, Z# Q4 c$ h2 D
    555-6699
    ( i! x9 o9 [, h* i555-6480
      g4 n4 ~% L$ @1 \8 w555-2127" k0 x9 P4 i. i5 |2 m
    regexp 也能使用在比较的算式。
    1 V% Z  a* I- [3 g  S8 ]( ~6 @exp ~ /regexp/
    4 K) H, B3 ^' N! k# v  j5 i. b如果 exp 符合 regexp,则结果为真(true)。
    8 I* ]9 g  s9 B. ~4 Iexp !~ /regexp/. Z! y( g! C8 D: i0 D
    如果 exp 不符合 regexp,则结果为真。
    / v$ W& d. a1 d2 |' ^  V: X/ f. \$ K, E) B
    5.3 比较的算式当作Patterns9 c" W) y: j! E* h7 |6 R4 K! H
    比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於. R, u8 I9 U/ H- D6 a3 y
    、小於。下面列出一些比较的pattern:
    4 U2 U1 \, U& W+ ]2 f( C; Ax<y 如果 x 小於 y,则结果为真。, s) ^( M+ P9 h4 @% P
    x<=y 如果 x 小於、等於 y,则结果为真。
    " [& T6 ~7 y+ Qx>y 如果 x 大於 y,则结果为真。% Y$ q( \) }7 q/ ^
    x>=y 如果 x 大於、等於 y,则结果为真。
    4 h, n' Z0 B, u7 Y% z+ px==y 如果 x 等於 y,则结果为真。
    " ?* r8 ~9 ^4 o+ |0 S- ox!=y 如果 x 不等於 y,则结果为真。% w" A9 {$ `  F
    x~y 如果 x 符合 regular expression y,则结果为真。
    : J+ N9 L# U+ Z: F  wx!~y 如果 x 不符合 regular expression y,则结果为真。1 o  \2 @0 G; l9 P
    上面所提到的 x 与 y,如果二者皆是数字则视为数字之间的比较,: Y; j+ X  C  }9 z- v3 C
    否则它们会被转换成字串且以字串的形式做比较。两个字串的比较,
    0 _/ R, g) h' {7 {0 c0 i2 j会先比较第一个字元,然後比较第二个字元,依此类推,直到有不同
    % P# L/ G6 M4 M1 R的地方出现为止。如果两个字串在较短的一个结束之前是相等,则视/ Q- n: O5 U" M  O! H3 ~9 |
    为长的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。+ |5 i) q! v0 x0 ?7 m5 X& ~7 M
      ^4 f' ~$ V+ H% R. H. q' s2 V
    5.4 使用布林运算的Patterns
    ! F. u( t' W6 ~* K7 r" L一个布林(boolean) pattern 是使用布林运算"或"('||'),"及"8 i2 \( l$ I3 ]6 T
    ('&&'),"反"('!')来组合其它的pattern。+ [, _2 O6 c% T1 @! p3 |7 A
    例如:" x: ]7 m  C8 j; y
    gawk '/2400/ && /foo/' BBS-list" l* f9 X8 a2 Q" q& R1 q8 V7 g
    gawk '/2400/ || /foo/' BBS-list
    & N7 p, C$ B3 k4 Agawk '! /foo/' BBS-list
    9 G, L' I' ?. W% C
    5 h* r+ f& ~7 l/ E. p) P: \第六章 算式(Expression)作为Actions的叙述* L1 ~3 X- i/ P4 |: I# v
    算式(Expression) 是gawk程式里面action的基本构成者。9 }7 R& v. l! a6 M4 Y7 ~3 ^
    0 O* z6 K: ~$ Y* h5 C
    6.1 算术运算4 q5 J$ t6 Z% Z! T; R
    gawk 里的算术运算如下所示:
    " a  B( ~, _7 H& }. R, B% S) cx+y 加& T: @# `8 m' U% v+ j* I/ L
    x-y 减
    8 r! P1 m6 s: x9 M6 Q  C  C; y. \$ J6 M-x 负
    5 L' ~( A$ X5 m: ?* f* {  x+x 正。实际上没有任何影响。6 c3 z8 h1 w( |  S
    x*y 乘
    : W, ~5 Y( z# A# t- A# \x/y 除9 ?& S* m/ r$ s8 }1 u# ~- E) [5 T5 C
    x%y 求馀数。例如 5%3=2。
    3 t1 ~) O) k- W( `3 Ex^y' Z- ?5 ^! B: m, E
    x**y x 的 y 次方。例如2^3=8。, c4 x( {- m# A+ K

    3 u7 H( {0 Y* h/ `/ ~1 ^" D, F  q  k6.2 比较算式与布林算式
    - e, _+ ?1 R: g3 v比较算式 (comparison expression) 用来比较字串或数字的关系
    ; H/ n4 D5 P+ R/ B,运算符号与 C 语言相同。表列如下:1 S* P" e' i- B( I  X8 ?/ g
    x<y. m2 V  S2 g  S" ^3 ?1 P% w& u
    x<=y
    $ x+ E7 k7 ~. w# r! Ix>y* [# N- Q  B+ ~/ e/ c( [
    x>=y/ ?4 y' j# T% ^1 N3 U/ h
    x==y* A) n5 `7 ]# z  R0 O: M, L3 [( z
    x!=y
    1 [  N  s! d9 y& _7 H- A+ Dx~y
    - V- s$ S) i" q9 R& L  j$ M1 Gx!~y
    % _# Q  ]% r9 V比较的结果为真(true)则其值是 1。否则其值是 0。" b1 e- P! L2 G- h9 }
    布林算式(boolean expression)有下面三种:
      B; @" w- G& x) p4 ^$ Zboolean1 && boolean2
    . e/ m  U$ p  L% X6 }boolean1 || boolean2
    1 r$ _+ w+ {. T9 L& H  r! boolean
    6 k: k! I0 P! y3 ]3 r& y1 [& U* A# v9 O" `% @
    6.3 条件算式(Conditional Expressions), R; z# E7 ~" E
    一个条件式算式是一种特别的算式,它含有3个运算元。( G' L9 O1 V, b
    条件式算式与C语言的相同:
    ' G8 E1 j6 c( Y9 a0 Eselector ? if-true-exp : if-false-exp% ]7 @9 a/ P3 K6 J" t
    它有3个子算式。第一个子算式selector 首先会被计算。如果是真,
    0 l9 g) f( E1 A* E5 j) e& w2 x# g0 h4 h则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-
    8 h) g: S7 p1 E! nexp 会被计算且它的值变成整个算式的值。
    ; o& H: m; T8 Y; K+ H2 b例如下面的例子会产生x的绝对值:! C$ F7 [/ m6 X: h, f$ ~* }
    x>0 ? x : -x% I7 k( c1 U# E) U1 s7 x
    $ R* c8 M4 l2 {; x) I4 f
    第七章 Actions里面的控制叙述/ U3 R; f3 k+ w% g* V+ M5 u  E
    在 gawk 程式里面,控制叙述诸如 if、while 等控制程式执行的流
    * t8 X. T0 ]6 ^9 N/ \程。在 gawk 里的控制叙述与 C 的类似。* [6 u1 c+ g# w8 |& c* C0 `  u
    很多的控制叙述会包括其它的叙述,被包括的叙述称为 body。假
    9 P/ t" d9 o7 \如 body 里面包括一个以上的叙述,必须以大括弧 { } 将这些叙述括起
    , t3 u+ l/ ~# u$ M8 D* e& l来,而各个叙述之间需以换行(newline)或分号隔开。
    ( u* n% I$ i6 b; V0 N. r$ y3 o7 O0 F$ V- }' }7 w
    7.1 if 叙述6 e% u+ P2 _$ D% n: q/ F/ I
    if (condition) then-body [else else-body]
    - d) r$ ?$ [; n& t& m如果 condition 为真(true),则执行 then-body,否则执行 else-body。
    - T  A4 ]1 W" R  c  K举一个例子如下:
    ( Y; G1 k5 H5 J! \if (x % 2 == 0)- f/ t! D% H- ]4 J4 u6 K
    print "x is even"9 C% u5 g: H; j( ], G+ r) o1 P7 p
    else( M' D" V+ k8 Q; N
    print "x is odd"5 l  {2 h: T3 ]& }# [! b( ]
    ' b) x: J" N: o  @
    7.2 while 叙述
    ! p8 l+ k' V: @. }8 [3 Swhile (condition)( s5 ~: s: {, B  L. F) Z
    body
    4 B4 l: s" V( O% U, ewhile 叙述做的第一件事就是测试 condition。假如 condition 为真则
    + B5 h- J0 q- n8 z执行 body 的叙述。body 的叙述执行完後,会再测试 condition,假如& {3 J& O: m$ w, z
    condition 为真,则 body 会再度被执行。这个过程会一直被重复直到
    / s' w8 i) z+ m) }3 ]" K4 ?condition 不再是真。如果 condition 第一次测试就是伪(false),则$ |  P4 j% s3 ^( a- L, q
    body 从没有被执行。
    2 |" a+ O; ?1 m8 D0 Q& A3 |下面的例子会印出每个输入记录(record)的前三个栏位。7 B" Z/ a% u2 t
    gawk '{ i=11 t% w  V1 E( c# u" p, U: _# f
    while (i <= 3) {  K! [5 _0 a! W. i5 c# Q9 b7 ?
    print $i( k7 T; i7 n/ U8 `% j
    i++% t3 g0 Q( \5 [, h0 X3 ~: u9 \
    }
    $ i  G8 I! z1 \$ d2 x9 ?6 V}'
    & s, [) H  f% {( v
    * }9 M% U/ J5 l1 p7.3 do-while 叙述
    3 f- i; i' f8 o. l* `% W/ D( tdo/ h7 F' j, h7 F  Q
    body
    . D" ^' V& b0 a( }/ uwhile (condition), q! ]6 _  v; W$ _8 \; h
    这个 do loop 执行 body 一次,然後只要 condition 是真则会重复执行 body。5 V! G1 g! n, q6 H
    即使开始时 condition 是伪,body 也会被执行一次。. I, \$ A" l  g' n3 }
    下面的例子会印出每个输入记录十次。6 ]4 I8 N$ U7 I+ O& d% p
    gawk '{ i= 1* }0 [+ n' z8 p, M' \& y
    do {$ t4 h- p5 s5 |$ Q7 n
    print $0
    * I. C4 e" Z  A  s! X& ji++
    ) [. j1 S' B1 M, @- J" i} while (i <= 10)
    " @8 b; c' S, W# y% A}', [1 u9 S" I/ A6 Z& }, M

    ; G1 W# \4 T2 c+ f7.4 for 叙述# @/ Z9 W5 R' p+ N2 J
    for (initialization; condition; increment)  W2 E6 @2 I( S; [1 h) k
    body6 ?* D$ k6 }9 W0 d% W
    此叙述开始时会执行initialization,然後只要 condition是真,它" E. I. G1 k. X" b  h8 K2 H
    会重复执行body与做increment 。$ I: w( [0 D$ V% B0 `5 g2 J
    下面的例子会印出每个输入记录的前三个栏位。
    1 l6 C3 A7 y* `gawk '{ for (i=1; i<=3; i++)
    # m2 l9 F, I8 I3 @# |0 l; tprint $i
    8 }/ M; ?; I& g4 p}'9 r) ^/ H. l9 \/ H0 ~
    7 C, U$ Y8 w9 t
    7.5 break 叙述
    8 _+ {( x; |9 f9 `" C, i8 [8 [& Dbreak 叙述会跳出包含它的 for、while、do-while 回圈的最内层。% k' M4 M) H- t1 I6 G
    下面的例子会找出任何整数的最小除数,它也会判断是否为质数。
      y9 q' d* ?- ^1 l& fgawk '# find smallest divisor of num
    " r0 T3 [) p" v7 J7 Q" a{ num=$1
    , k) ]# ^3 o' S# o1 U6 v% f! mfor (div=2; div*div <=num; div++)
    : i7 R' n0 ]! F* ^% G( T' U! ^* tif (num % div == 0)
    : w6 F, v6 a5 _' J+ W" x2 Zbreak6 n8 ]1 s  _, \! f
    if (num % div == 0)
    7 W- a# i  h" q& W  x; E# I4 I* Nprintf "Smallest divisor of %d is %d\n", num, div) y7 h; u' p: q( P/ k, Y  p
    else$ J" f3 n1 c: }9 Q
    printf "%d is prime\n", num }'! V6 e5 h$ P5 Y: H& f" d8 \
    ; Q! T" c; t( Y) N& d! Y  G
    7.6 continue 叙述9 e- ^3 C0 z. R
    continue 叙述使用於 for、while、do-while 回圈内部,它会跳
    - F, |! O( F! d' H5 U- L过回圈 body 的剩馀部分,使得它立刻进行下一次回圈的执行。4 m+ H7 O5 o  Q: ^5 T: G! a9 j5 G/ d. A& \
    下面的例子会印出 0 至 20 的全部数字,但是 5 并不会被印出。
    ! P  l) B. y( _' r8 xgawk 'BEGIN {
    - l1 s- f9 s( j+ Sfor (x=0; x<=20; x++) {( U- t& X" I% W
    if (x==5)
    ) ]0 j7 n# }6 _7 ^  dcontinue9 p# ]" s# k. x/ G7 f6 O7 d7 B
    printf ("%d",x). Z# W* |8 `" m+ w, ]. f2 \9 M
    }
    - x2 F+ f3 K7 c# aprint ""
    9 Q5 s4 L" f* l7 b' E/ w: m! X}'7 D0 i8 e# m5 k% F" H2 P) a/ G

    0 h7 f3 K+ ]7 X) z: R9 N' H) p3 g7.7 next 叙述、next file 叙述、exit 叙述
    / T8 `- b. w+ K6 ?- Z- `' R8 mnext 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一
    # w6 A9 Q  j7 t( k6 e1 J个记录。
    / G7 j9 I4 t8 P& C3 lnext file 叙述类似 next。然而,它强迫 gawk 立刻停止处理目前
    + B) N7 h, S4 u! i, ?+ G0 n的资料档。: d, z8 l( f5 z- ?1 n: Y
    exit 叙述会使得 gawk 程式停止执行而跳出。然而,如果 END 出现# {/ m' _4 P1 q9 N; z# W, a
    ,它会去执行 END 的 actions。2 O0 [1 f8 C4 }5 G8 u7 Z

    7 M- H1 m& f$ r第八章 内建函式(Built-in Functions)0 m% E. ~$ ]* m4 }8 j
    内建函式是 gawk 内建的函式,可在 gawk 程式的任何地方呼叫内建% j/ i% m" U' G+ g3 w# O7 y
    函式。
    $ n, ~. s0 s3 ~8 \
    ; Y  Z9 a0 F' |: n* v" z& D" Y7 H. x8.1 数值方面的内建函式5 {  B: E1 d9 ^3 |* \! V: E
    int(x) 求出 x 的整数部份,朝向 0 的方向做舍去。例如:int(3.9)0 E! X) ~4 q0 \( j( X$ {* C
    是 3,int(-3.9) 是 -3。
    ( r" e0 u6 J1 j5 Jsqrt(x) 求出 x 正的平方根值。例 sqrt(4)=2
    5 b8 G+ e! L8 X7 Z$ H) p8 Sexp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。
    ( ]8 r9 b$ `& }' Q! s1 d3 Ilog(x) 求出 x 的自然对数。! I! ^. V+ U% ~
    sin(x) 求出 x 的 sine 值,x 是弪度量。
    ) ]! D& ^' Q; @0 B8 O: Q* q' x7 |cos(x) 求出 x 的 cosine 值,x 是弪度量。2 _+ y6 Y  r! F& x2 j
    atan2(y,x) 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。2 {" s* s6 A( H  C& b& F
    rand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个
    + @" J8 W2 Y0 {' l值不会是 0,也不会是 1。
    2 X. @& L; G; e! h9 Y每次执行 gawk,rand 开始产生数字从相同点或 seed。$ c, I! r, f( g3 z! g( U9 K
    srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设/ F5 u6 ], L( w7 u+ L
    定相同的 seed 值,你将再度得到相同序列的乱数值。
    / e; b* Y0 V: E4 A5 ^, D如果省略引数 x,例如 srand(),则现在的日期、时间会3 E+ E' b/ m3 r; A( A/ g3 i5 Y1 U
    被当成 seed。这个方法可使得乱数值是真正不可预测的。5 Z" x! H; n* f3 H
    srand 的传回值(return value)是前次所设定的 seed 值。6 h; p; V! D- e: m3 L. J/ Y: G
    # I1 A8 @0 ~9 [2 n3 ^, h( H2 q
    8.2 字串方面的内建函式
    ' h) ?- E# k+ F6 Qindex(in, find)
    9 g1 M5 B& @, g: y它会在字串 in 里面,寻找字串 find 第一次出现的地方,传回值是
    ' [2 l# \" x! t& k( z& ~字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字0 K* x" d6 v) h: ~4 I
    串 find,则传回值为 0。3 J7 x+ ^- d. [+ r+ ^
    例如:
    : U& `7 r+ p1 C  @print index("peanut","an")
    " a! b2 k5 y0 h: j5 Y& n" f会印出 3。
    7 N9 M! |7 K. ~) G5 U) `: `# [length(string)% s" c; B+ D  d5 l6 F0 ^
    求出 string 有几个字元。
      B# p' p$ P9 \# T- I/ B# I例如:
    ! ^2 {) t# T9 q9 Ulength("abcde")
    6 m% \) i, R" a+ F9 ?* X是 5。; R- w/ L1 c) j
    match(string,regexp)* }$ Q. d& j$ P- I  l8 m
    match 函式会在字串 string 里面,寻找符合 regexp 的最长、最靠2 @& c9 c3 Q, h$ B7 O; o8 `
    左边的子字串。传回值是 regexp 在 string 的开始位置,即 index
    * \9 _( D( v5 J: S3 N( l# k值。
    & f: {- Z3 b; |/ s% A' q7 w) vmatch 函式会设定内在变数 RSTART 等於 index,它也会设定内在变
    1 ?& W1 L! p) c( N% `% l& E数 RLENGTH 等於符合的字元个数。如果不符合,则会设定 RSTART 为" |2 P6 L8 a4 y1 _) h
    0、RLENGTH 为 -1。" X9 {9 h0 V& R2 C* A% U& R; ^
    sprintf(format,expression1,...)3 n. n1 a5 C  F5 p5 y1 Q8 O
    举 printf 类似,但是 sprintf 并不印出,而是传回字串。
    # z0 W! v6 _# ~/ z4 D" j例如:
    9 n3 B, K3 F/ D* ?$ d$ csprintf("pi = %.2f (approx.)',22/7)% M+ b1 R) g$ [+ i6 r
    传回的字串为"pi = 3.14 (approx.)"" u1 b7 @& \0 O1 }  v
    sub(regexp, replacement,target)
    2 x" m3 t& t, O3 O* e) f在字串 target 里面,寻找符合 regexp 的最长、最靠左边的地方,
    ! l. ^4 h1 T" a/ E, g9 V/ n以字串 replacement 代替最左边的 regexp。
    ; b# ?- c0 v  Y) e  r2 p4 s例如:  T  i% D$ ]+ C7 I) k. e
    str = "water, water, everywhere", l4 m: N; o' |2 I. c2 K
    sub(/at/, "ith",str)
    2 [, U: W# Y/ |, R结果字串str会变成
      A$ }5 z( n7 x/ H( e"wither, water, everywhere"
    % |, t4 j" J2 m; `& h  f# Sgsub(regexp, replacement, target)
    4 J4 O7 [" J4 l! \gsub 与前面的 sub 类似。在字串 target 里面,寻找符合 regexp 的
    + s9 d& D2 ~# n所有地方,以字串 replacement 代替所有的 regexp。
    . G# J, @! G$ R3 M% j例如:
    1 \  s/ W' \" w1 C  O  Fstr="water, water, everywhere"
    / m1 w7 V! R& r1 tgsub(/at/, "ith",str)
    % Y5 B0 t  q8 a" `( j! ]7 \结果字串str会变成
    4 s3 ^/ n0 ~  x8 [" u9 v'wither, wither, everywhere"5 L8 Q9 U/ ~  z9 B  Z- l6 ?3 h
    substr(string, start, length)/ F* @- a; t7 E, d/ L3 H
    传回字串 string 的子字串,这个子字串的长度为 length 个字元,
    5 k! \$ }$ D3 g2 j* M, ?- c, Y. z3 B从第 start 个位置开始。- N( e0 `; `5 {& U' i$ ~9 D, _
    例如:1 v9 S9 }+ M/ W3 b
    substr("washington",5,3)" k3 b1 a) \7 G+ p3 M# u
    传回值为"ing"
    + m1 Q6 {* l' |0 F, C3 ?  _如果 length 没有出现,则传回的子字串是从第 start 个位置开始+ c5 X) K# c3 R( x0 C
    至结束。
    2 R- [- O4 d' ?5 T例如:
    9 N) v  d' V, osubstr("washington",5)2 l# Z1 U. u; |. h+ X- a7 J
    传回值为"ington"
    # d$ j8 l. T& j6 Ztolower(string)7 v$ V& ]0 h$ p( P. ]. h4 v% {$ V
    将字串string的大写字母改为小写字母。
    ' d! m2 q( ?% H5 Y3 F: }4 B例如:
    / C+ ]! S! n' }1 Dtolower("MiXeD cAsE 123")
    # w) k6 B# T- J  {# P传回值为"mixed case 123"
    0 y( L7 S/ ?0 Z' v' ?toupper(string)  f+ X5 E8 {( o/ i& ~- V
    将字串string的小写字母改为大写字母。* X4 s" R& t" z7 Y: q& F
    例如:
    " T1 e7 m4 B% ~5 Utoupper("MiXeD cAsE 123")
    : p9 h. Y+ K& b7 p7 j! L传回值为"MIXED CASE 123") @# }! ~/ `" N
    - V) d5 }1 @% o: Z3 s
    8.3 输入输出的内建函式& W5 i: S7 J- O6 J
    close(filename)  W- l( K; P3 M' X+ F! T7 S
    将输入或输出的档案 filename 关闭。5 O' I( A2 b& G5 J
    system(command)
    , ]7 o. {* @$ @. n8 Z此函式允许使用者执行作业系统的指令,执行完毕後将回到 gawk' v, w( y2 {& n0 l, u! N* ~1 @; ^4 m
    程式。
    8 G/ n' {& r* h* G. H) Q) Q5 h) }例如:1 T! F- Y! S# y4 d& R
    BEGIN {system("ls")}; ?, a9 B! o3 M1 Z- M6 \
    6 B: R- S9 z8 D% U
    第九章 使用者定义的函式(User-defined Functions)0 ~0 f' F$ J7 d
    复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用
    9 H2 f0 ?) C/ f4 O者定义的函式与呼叫内建函式的方法一样。& p& d( \' l( `/ W4 P# w
    . M, H! d' I: T8 v, M) r3 D
    9.1 函式定义的格式1 b/ Q; L7 j; R# c# U9 n% k
    函式的定义可以放在 gawk 程式的任何地方。9 b3 ?/ R5 {& g7 e
    一个使用者定义的函式其格式如下:- t: A, d0 G- [7 m" u
    function name (parameter-list) {. H, V  J9 T* j- e2 E8 y( X& t2 ?: ~' X
    body-of-function
    - W: \. J0 P: ~. p" X- B7 S}
    , ], `0 r% f& y+ i/ [/ ~6 Yname 是所定义的函式之名称。一个正确的函式名称可包括一序列的字
    6 H) p5 {7 o$ j* ]( V- l$ V3 W母、数字、下标线 (underscores),但是不可用数字做开头。# c" v- R0 I- ]) k: q0 {) u
    parameter-list 是列出函式的全部引数(argument),各个引数之$ b" O" |3 A* L1 }  W# \$ M
    间以逗点隔开。1 v% T% H/ a7 I+ n* I$ Y5 R
    body-of-function 包含 gawk 的叙述 (statement)。它是函式定义
    % J5 X& K! L* r( A8 o: O% ?里最重要的部份,它决定函式实际要做何种事。
    / Q% e6 l6 o2 B, O4 R+ `1 X* [5 T$ @( K7 g7 s  `
    9.2 函式定义的例子5 [' g' M4 i# K
    下面这个例子,会将每个记录的第一个栏位之值的平方与第二个; H+ S; s$ O( w& r; J
    栏位之值的平方加起来。0 r! f7 v, y! v4 b+ i9 M' a
    {print "sum =",SquareSum($1,$2)}- q  c+ ?% A6 x$ o% i! k6 n
    function SquareSum(x,y) {# F( I& s# T# H" C% ~; W$ W
    sum=x*x+y*y+ t% b! K. L4 x
    return sum
    3 H$ X5 C3 v: O" n, m}
    - }( Y% N+ A* C" x6 ^1 D6 X! Q' Z3 X7 c9 r, w$ x9 @, \; J( O
    第十章 □例
    ; o4 M8 n( T0 i" E; V% g这里将列出 gawk 程式的一些例子。3 G- G: b8 g( P* [4 S6 C
    gawk '{if (NF > max) max = NF}
    ) |: ^/ W' a5 wEND {print max}'1 ^3 N0 N" Z+ ^
    此程式会印出所有输入行之中,栏位的最大个数。
    9 W( ?- M0 U" f9 c7 Agawk 'length($0) > 80'
    / q6 X  Z+ g2 F0 o" P2 H" b5 J此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被
    & b; s7 w9 S) q9 y! a; N1 l2 d! r列出,action 是采用内定的 print。# f4 J; _: k# y: L
    gawk 'NF > 0'
    ) x5 k8 d2 R: u7 M对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简6 }* \) H! X/ P- R- H
    单的方法,将一个档案里的所有空白行删除。
    ( d5 ?9 N0 m% A+ S, B* Wgawk '{if (NF > 0) print}'& N3 d* [* R) L, e% M! Y- J0 |, W
    对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简( z' [# ~9 m/ k% U
    单的方法,将一个档案里的所有空白行删除。% y, i7 [* ^& H4 X, x$ J
    gawk 'BEGIN {for (i = 1; i <= 7; i++)
    " W# _+ W+ [) h: T7 Xprint int(101 * rand())}'1 R1 @4 h- i, w9 f. c
    此程式会印出□围是 0 到 100 之间的 7 个乱数值。
    % H' J1 {( D) @  Kls -l files | gawk '{x += $4}; END {print "total bytes: " x}'- _9 n, g* n9 W/ B
    此程式会印出所有指定的档案之bytes数目的总和。
    ; M$ H9 l* e0 S7 |8 ]3 y, g+ Rexpand file | gawk '{if (x < length()) x = length()}1 d7 ^2 v* j$ R" i; g/ M
    END {print "maximum line length is " x}'4 [: R1 b+ ~/ m  K, o) e' t
    此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改9 x+ m' x5 s$ b: t" s" T
    成 space,所以是用实际的右边界来做长度的比较。
    7 V& Z2 d/ R% Z/ ~* H0 ~# Ogawk 'BEGIN {FS = ":"}
    / Y7 H1 r9 f  Y2 t{print $1 | "sort"}' /etc/passwd) S) R) r- R6 P/ B# L5 `2 A
    此程式会将所有使用者的login名称,依照字母的顺序印出。* G( t  P: u9 g4 W, b4 s$ v
    gawk '{nlines++}
    6 n  ]; c$ q" jEND {print nlines}'
    6 l: F4 ~% U$ r! ]8 M此程式会将一个档案的总行数印出。/ d7 X$ B0 v( w5 J+ `
    gawk 'END {print NR}'7 s' z$ S- {1 Q$ s9 l+ f
    此程式也会将一个档案的总行数印出,但是计算行数的工作由gawk- N; l* ~& u5 z! R+ h; E
    来做。
    # W. V# \& J1 p2 K9 U7 s. xgawk '{print NR,$0}'" @/ G  [) R. d; ^9 k/ b3 e& h
    此程式印出档案的内容时,会在每行的最前面印出行号,它的功
    2 Z, I0 R" [' c% W能与 'cat -n' 类似。( [% P/ D# a- n0 M: l. t6 `

    / w+ H! }! K* s% R+ i$ h第十一章 结论
    3 ?( g) z& _. P4 Ogawk 对於资料的处理具有很强的功能。它能够以很短的程式完成! t6 E8 R. z' Z7 _; X% j2 F* p
    想要做的事,甚至一或二行的程式就能完成指定的工作。同样的一件
    ) N1 ^6 C/ r1 q工作,以 gawk 程式来写会比用其它程式语言来写短很多。/ c, R6 H' ?! y) l0 j. G
    gawk 是 GNU 所做的 awk,它是公众软体(Public Domain) 可免费使% m; E, }( `6 w) U; C
    用。
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    楼主热帖

    相关帖子

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

    该用户从未签到

    尚未签到

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

    本版积分规则

    招聘斑竹

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

    GMT+8, 2026-10-9 22:50

    Powered by Discuz! X3.5 Licensed

    © 2001-2026 Discuz! Team.

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