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

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

Gawk手册

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

    连续签到: 1 天

    [LV.1]初来乍到

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

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

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

    ×
    GAWK' N  p/ {9 g6 _& ]( j) t
    第一章 前言
    $ {$ e6 C/ y/ z0 r2 A) b第二章 简介. L+ p: }+ I' Q4 k6 y! H* \
    第三章 读取输入档案6 v4 J8 E5 F2 E5 z) x( K6 o/ Q! x
    第四章 印出9 {9 t/ n& \* A3 {" p: H; Q
    第五章 Patterns
    : M6 ^( z0 {4 k第六章 算式(Expression)作为Actions的叙述7 C$ D! ]* ~- A  g1 {1 H
    第七章 Actions里面的控制叙述
    - l3 `" b* e, c' T第八章 内建函式(Built-in Functions)8 V( u% x1 g/ g+ w* @; R7 ?. j
    第九章 使用者定义的函式
    ( j3 ?7 d( P3 Q* D& R第十章 □例
    - d; F$ ?1 j& [% {1 o第十一章 结论4 x6 s% {. Q6 i# K" \8 x

    ' u$ U. j4 i7 |! |5 P) V=======================================
    ) y. Z) d4 ^' k  _第一章 前言, o. B6 I1 p0 {. X! s1 L! \2 w
    awk 是一个程式语言,对於资料的处理具有很强的功能。对於文& @1 `/ r1 K; j7 o  }
    字档里的资料做修改、比对、抽取等的处理,awk 能够以很短的程式; z' t& X! p' w) k) J
    轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作,
    - W, ^: e: H2 @: }1 w会不方便且很花费时间,所写的程式也会很大。
    6 H* x! }* ^, t9 Iawk 能够依照使用者的定义格式来分解输入资料,也可依照使用9 _; o0 P7 L+ t; f6 n9 x
    者定义的格式来印出资料。" d# ?, `+ M4 O8 z, Y
    awk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名" R) K& a1 }3 u1 H- I& g
    :Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。
    7 A3 P+ D1 A2 A; A2 X& E! C3 `awk最初在1977年完成。一个新版本的awk在1985年被发表,它的功能
    : [) v2 s( T) d* l' ~比旧版本增强不少。7 K: \3 ?; j; L0 M/ k8 z  V! |
    gawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不断地, S$ ?" X1 v0 }9 p9 P1 j
    被改进、更新。gawk 包含 awk 的所有功能。
    $ S, h9 s# {' I0 e% M* p6 {3 N# ~往後的 gawk 将以下面的2个输入档案来做例子说明。
    2 K/ k2 U8 V# Z: |2 ]- C档案'BBS-list':
    9 ]2 @: R1 }: J& U- |aardvark 555-5553 1200/300 B
    3 U! M: E9 p& X5 K- Q# Yalpo-net 555-3412 2400/1200/300 A9 w( }0 C, F  w$ `7 W) q% C
    barfly 555-7685 1200/300 A
    , @( m, I9 t' V7 ^3 H, Zbites 555-1675 2400/1200/300 A  n6 K2 g. C8 A+ ?6 U. }- A
    camelot 555-0542 300 C/ n  W- O( h+ l
    core 555-2912 1200/300 C5 K- k2 O6 E$ [. `6 ~; K
    fooey 555-1234 2400/1200/300 B
    ' N8 _) K" I$ f4 Jfoot 555-6699 1200/300 B
    * ?- M9 y& C- A# k+ K6 xmacfoo 555-6480 1200/300 A% D# A) |  [8 }& }
    sdace 555-3430 2400/1200/300 A
    * W9 R' O! J  A# x, N; Fsabafoo 555-2127 1200/300 C
    # `6 u" R; L+ S! W8 F档案'shipped':  Q1 ]  `) k# M" ~9 C4 m4 F
    Jan 13 25 15 1159 y* K# Y3 a+ y3 Y
    Feb 15 32 24 226( G6 e' {' K; q4 y& `+ r7 d2 g- o
    Mar 15 24 34 228
    8 P% _( j) Z3 ]5 Q! ?Apr 31 52 63 420! C% n4 R) m) D4 N0 ^
    May 16 34 29 208
    7 U  u$ a, _3 c( uJun 31 42 75 492% v2 k6 L" q  A! m4 i
    Jul 24 34 67 436
      g" I# J4 Q! pAug 15 34 47 316' e/ t6 X" ]  ~% J* @6 l4 L. g$ Y
    Sep 13 55 37 277
    ' i6 i; j; T( g' E% Q/ ?1 k5 |Oct 29 54 68 525
      C3 [) J- ~  d9 T! O. h/ WNov 20 87 82 577
    1 z7 j+ g/ [0 v6 \Dec 17 35 61 4019 ~; R3 s, A$ s  |
    Jan 21 36 64 620
    ( ?% P! k( |" e$ K8 ~1 c" hFeb 26 58 80 652
    ' Q/ F! x  C4 i1 ~2 K, HMar 24 75 70 495( K& Y: Y* M6 u1 i: K
    Apr 21 70 74 514
    2 i8 _. V: m8 q! m0 V2 g
    # X" n$ s7 F- m, t第二章 简介/ L, l: H- c2 G( s! q0 o! ^
    gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns
    - T8 F3 n" M, u  q) I。当一行里有符合指定的 patterns,gawk 就会在此一行执行被指定8 a" Y9 [& N! W1 j" L
    的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结
      E' @* w$ b! e束。
    / ^/ R( ~! u8 e2 `% Y; Xgawk 程式是由很多的 pattern 与 action 所组成,action 写在
    ! L8 Y3 E. w& K1 N大括号 { } 里面,一个pattern後面就跟著一个action。整个 gawk 程
    : t) ~) n: h) j, A" u式会像下面的样子:
    0 I5 Y/ |, [, t+ \pattern {action}
    # B% r" X/ o. O7 F* {8 \; ~5 mpattern {action}
    % ^# M& l' q3 ]# C; I在 gawk 程式里面的规则,pattern 或 action 能够被省略,但2 h4 w, \2 h/ |$ D# u
    是两个不能同时被省略。如果 pattern 被省略,对於输入档里面的5 z7 F1 m0 v. v) b% L3 I$ d& b
    每一行,action 都会被执行。如果 action 被省略,内定的 action3 `7 S5 [. p5 q7 j
    则会印出所有符合 pattern 的输入行。2 ^) r- O& U! V

    8 n8 b9 N" T6 j* }$ k% C2.1 如何执行gawk程式  ?5 g5 g' @+ L( Z% I2 E0 |
    基本上,有2个方法可以执行gawk程式。1 h1 U4 A  a# Q: M
    □如果 gawk 程式很短,则 gawk 可以直接写在 command line,如下所示:
    8 D* d% z; s% n4 t5 Rgawk 'program' input-file1 input-file2 ...% D! Y! D. N. `! N$ f# ^% V
    其中 program 包括一些 pattern 和 action。
    & R7 @" O9 v2 ]. W3 Q2 _2 H□如果 gawk 程式较长,较为方便的做法是将 gawk 程式存在一个档案,
    4 A* v! I, _3 n; s即 patterns 与 actions 写在档名为 program-file 的档案里面,执行
    5 }4 {" D: x7 }! L1 A- Q' Agawk 的格式如下所示:
    9 k; o( s( ~. d2 `: l. |# Y% zgawk -f program-file input-file1 input-file2 ...
    / |+ U& i1 {: T" y$ Zgawk 程式的档案不止一个时,执行gawk 的格式如下所示:
    . X6 z9 T- P0 j" g' T0 l+ rgawk -f program-file1 -f program-file2 ... input-file1
    2 F1 ]% Q0 I: p! u2 a- Uinput-file2 ...  x' e6 E$ O; l
    ' j# E( j  W1 D2 O& g/ |6 t' l) Z
    2.2 一个简单的例子5 t7 [" x$ S# B7 `! H3 ^$ I" N
    现在我们举一个简单的例子,因为 gawk 程式很短,所以将 gawk 程
    5 s: G* {  ~: d5 u式直接写在 command line。
    % U- e7 }7 B. \; Igawk '/foo/ {print $0}' BBS-list4 t. b8 J: g2 B
    实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern,意思为搜" J' Z) _0 L' R4 f0 \
    寻输入档里的每一行是否含有子字串 'foo',如果含有 'foo' 则执行 action。3 [! ^' j  U/ V# y; n' c
    action 为 print $0,是将现在这一行的内容印出。BBS-list 是输入的档案。4 E9 L% R% M/ T" X6 I# u
    执行完上述指令後,会印出下面的结果:9 y6 G+ f; }+ X3 \% D
    fooey 555-1234 2400/1200/300 B
    & t7 R3 y* N  ?7 _6 k5 M/ cfoot 555-6699 1200/300 B
    ) T* p, Y) h! D9 omacfoo 555-6480 1200/300 A
    4 B( w' v6 V6 D7 Vsabafoo 555-2127 1200/300 C  V) ?) e  S7 D- E

    3 [  H2 Q1 Q. t- l+ n2.3 一个较复杂的例子
    # i' M3 U  j% ygawk '$1 == "Feb" {sum=$2+$3} END {print sum}' shipped2 q3 ]2 S& d2 l8 ^6 {* c! h6 r& w
    现在这个例子会将输入档 'shipped' 的第一个栏位与 "Feb" 做比较
    # V$ _- u% ?' G) Z* f,如果相等,则其对应的第2栏位与第3栏位的值会被加到变数 sum。' H5 _- s% }3 J0 U
    对於输入档的每一行重复上述的动作,直到输入档的每一行都被处理
    7 I, e4 }# y' R7 |过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输1 L3 g4 U2 K3 N$ ~" V
    入读完之後,执行一次 print sum 的动作,也就是把 sum 的值印出。6 `' B% k7 h: {
    下面是执行的结果:
    ; i4 i' i/ M6 a! |  q) s84
    ' y0 v; y" j% j6 u% p  p6 I
    4 x5 Z3 T4 y. B3 L第三章 读取输入档案) B9 @' Z8 a8 w) L
    gawk的输入可以从标准输入或指定的档案里读取。输入的读取单
    0 t: Y( |% I% d2 l1 @位被称为”记录”(records),gawk 在做处理时,是一个记录一个记
    ! L' f0 b# n3 b, X- d录地处理。每个记录的内定值是一行(line),一个记录又被分为多个6 v) [4 p7 Z, p6 h+ ^
    栏位(fields)。: o3 B" ?. U$ m" p; V

    ' G0 k7 i7 E4 m8 b" N6 J* H3.1 如何将输入分解成记录(records)
    / p- d  u% a; p3 k4 [gawk 语言会把输入分解成记录(record)。记录与记录之间是以, o+ D4 M' [/ K2 q% S* u5 u
    record separator 隔开,record separator 的内定值是表示新一行的
    & A3 _& `4 d; W, t字元(newline character),因此内定的 record separator 使得文字
    4 i* ^% _+ l6 @6 v5 Y+ _的每一行是一个记录。
    ) f- }( D* o6 M7 h, grecord separator 随著内建变数 RS 的改变而改变。RS 是一个字串,
    ( V. i) Q# R# f0 d/ e9 i它的内定值是"\n"。仅有 RS 的第一个字元是有效的,它被当作 record/ S$ ?# q5 R5 A. }# R' Y! w) ]3 P
    separator,而 RS 的其它字元会被忽略。5 Y; L# y8 \7 M9 ~+ Q" H
    内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内- n. r0 j! {9 D2 U" i4 b
    建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。
    ; y$ i) K7 ~6 u* |% s8 X6 H/ P: y) S0 Z# \; L' O
    3.2 栏位(field)
    : F4 P8 @) c0 D5 S# Cgawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一
    $ U7 d! X; U. k1 N. ^0 ~行里面,gawk 的内定动作会认为栏位之间是以 whitespace 分开。在
    & W' e$ v- P2 u4 [gawk 里,whitespace 的意思是一个或多个空白或 tabs。! H) d. s( n- X9 e/ e& J
    在 gawk 程式里面,以'$1'表示第一个栏位,'$2'表示第二个栏位* i( Q% q5 X! e" F& |6 p& @
    ,依此类推。举个例子,假设输入的一行如下所示:1 T2 W3 i: Q6 ?6 I3 N
    This seems like a pretty nice example.) ~" }' B7 M! ^
    第一个栏位或 $1 是'This',第二个栏位或 $2 是 'seems',依此类推。8 z/ w5 M  T- R4 ~/ ]7 X! ]8 h- p
    有个地方值得特别注意,第七个栏位或 $7 是'example.'而非'example'。. A( X4 Q5 y  ]) [# k. c: K
    不论有多少栏位,$NF 可用来表示一个记录的最後一个栏位。以7 s: I1 B1 q( W8 L
    上面的例子为例,$NF 与 $7 相同,也就是'example.'。4 E# P' Y1 f) [6 o0 k4 U
    NF 是一个内建变数,它的值表示目前这个记录之栏位的个数。! M6 n* B" D: A" Y9 s2 Y. i# {
    $0,看起来好像是第零个栏位,它是一个特例,它表示整个记录。
    ) F' k" _- O  j2 Z下面是一个较复杂的例子:
    * ^2 G' b' J0 @, @! Ogawk '$1~/foo/ {print $0}' BBS-list1 |/ |$ j4 {4 D' h9 b! L* k
    结果如下:
    . m5 Y! k' m  e7 k3 x9 cfooey 555-1234 2400/1200/300 B
    8 t4 p( |1 O2 W1 R9 k' {foot 555-6699 1200/300 B6 U4 t6 l8 O& K- T  O
    macfoo 555-6480 1200/300 A9 r. [) }8 k# ^+ M
    sabafoo 555-2127 1200/300 C
    3 |; Y9 k/ A; V4 i& x6 O这个例子是把输入档'BBS-list'的每个记录的第一个栏位作检查,如; B' q, e8 z$ w) `7 {: Z
    果它含有子字串'foo',则这一个记录会被印出。# [( \- v4 z8 O
    & T# y% M" q+ Q  G$ g! Y  C; Z2 g8 P
    3.3 如何将记录分解成栏位) v- F- }* S( k' p0 V' T% ~0 _
    gawk 根据 field separator 将一个记录分解成栏位。field sepa-
    # ]& H0 Z$ r9 Y8 r5 t7 ?9 drator 以内建变数 FS 表示。
    2 L" p2 {4 h$ ]$ w/ U3 j2 R* A+ p举个例子,假如 field separator 是'oo',则下面的行:; k0 p2 Z3 H+ z  w: l+ ~6 }" F
    moo goo gai pan0 |5 J8 W) Y2 B6 O/ O2 ?, L
    会被分成三个栏位:'m'、' g'、' gai pan'。
    4 L  C: I* u3 x/ P在 gawk 程式里,可以使用'='来改变 FS 的值。例如:
    0 b0 F- d8 N! ]9 x  X4 i4 igawk 'BEGIN {FS=","}; {print $2}'
    - w+ N5 x* ~( v1 ]5 k- `/ u- i0 N5 v输入行如下:
    7 E9 ~+ V' s" y: mJohn Q. Smith, 29 Oak St., Walamazoo, MI 42139
    " y0 w* S9 G( k+ t* [$ v# Q执行gawk的结果将印出字串 ' 29 Oak St.'。BEGIN 後面的 action 会在
    $ |9 X* z1 C# l% V% E& \1 A第一个记录被读取之前执行一次。7 r8 Q! _& d3 U$ k8 n- u
    % W4 ]/ G% M' j8 v/ _% j
    第四章 印出5 v( R0 [0 z+ R! [7 Q/ \/ w9 ~
    在gawk程式里,actions 最常做的事就是印出(printing)。简单
    . ~4 b2 G/ P5 R- G9 B; |的印出,使用 printe叙述。复杂格式的印出,使用 printf 叙述。) z+ I  {) P6 o# w

    / `6 F4 f; U/ U1 ?/ l8 z( [4.1 print叙述% r% f$ U5 D. R& e. R
    print 叙述用在简单、标准的输出格式。叙述的格式如下所示:
    + x$ _9 z1 F0 p+ Xprint item1, item2, ...
    5 W5 j6 X9 r7 S9 X+ {输出时,各个 item 之间会以一个空白分开,最後会换行(newline)。
    , N% e7 a, ]8 U( o9 \如果 'print'叙述之後没有跟著任何东西,它与'print $0'的效+ K6 q' r" z9 u3 p7 B, d5 f
    果一样,它会印出现在的记录(record)。要印出空白行可使用'print& Q& p) C+ m8 o1 r8 m- _8 o" G& y
    ""'。 印出一段固定的文字,可用双引号将文字的两边括起来,例如
    , n3 V- ^+ @9 i'print "Hello there"'。' H: V' W) a; J  v
    这里是一个例子,它会把每个输入记录的前二个栏位印出:+ G9 f% s6 _6 ?% _
    gawk '{print $1,$2}' shipped5 r4 i- @8 [  }/ I8 J$ r- t
    结果如下所示:
    + `! J7 k+ U" }Jan 13
    ( M* Q$ U- Z% t& {: V" O2 BFeb 15, ]* z% O! @% H* H# n- f; `0 s; b
    Mar 15
    7 j- |7 }1 v' U0 TApr 310 u1 H1 S; n0 d4 j; g
    May 16: @+ H& e: F- ]% \$ [1 k
    Jun 31
    6 c& h4 b! K2 |: b; r1 x4 PJul 24
    9 s0 D/ n4 p: H' K& v! nAug 15
    9 @9 U  X& _  w; D& p0 P6 ^; rSep 13
    " m9 ~; G: ^7 c2 U( |8 C/ ^% a+ [9 {Oct 29
    , C5 M% K7 A  k& e% U; S, h" {. TNov 20( _+ j, f1 G! x
    Dec 17
    % x/ r$ {: I$ y. }: KJan 21
    , }( g2 j5 m( c% c9 cFeb 26
    2 K/ j6 A8 T$ v1 @: }; IMar 24
    4 a2 F9 K/ b1 |Apr 21. [$ ~" p, w) S. S$ b
    : w5 n: h# `# [) Y3 B) Z
    4.2 Output Separators
    ) J" a8 [% r8 p, _前面我们已提过如果 print 叙述包含有多个 item,item 之间& n* X5 a- W& \  J' R
    用逗点分开,则印出时各个item会被一个空白隔开。你能够使用任何6 f1 D% n! |/ N8 M
    的字串作为 output field separator,可以经由内建变数 OFS 的设  {" q3 i% m) U
    定来更改 output field separator。OFS 的初始值为" ",即一格的
    . C. j" f; g3 ~空白。
    8 l: F: K& `) j' t* U6 `6 X- `整个 print 叙述的输出被称为 output record。print 叙述输7 o" _  m: q5 E7 F: A3 B& T! ]& f
    出 output record 之後,会接著输出一个字串,此字串称为 output% s! ~+ ^, u7 Z  K# B4 u
    record separator。内建变数 ORS 用来指明此字串。ORS 的初始值, X; i  B3 x, P6 k+ G/ t, s
    为 "\n",也就是换行。
    ; P2 h( _7 w1 V7 ^3 Z3 c下面这个例子会印出每个记录的第一个栏位和第二个栏位,此二/ J: w3 F' y" K  B+ `, {  Y
    个栏位之间以分号';'分开,每行输出之後会加入一个空白行。9 z# Z" w0 R& |% v6 h7 x
    gawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list! Z$ q2 z! N6 F1 g3 [
    结果如下所示:  Z" s# p% c. u
    aardvark;555-5553
    . S4 S' H1 y; q2 ^# z+ Y) balpo-net;555-3412
    6 O; D' X# M9 U0 F0 |2 kbarfly;555-76859 u' C$ J0 I( [  O3 Y
    bites;555-1675: |7 }/ C- u" F/ Z) d7 K
    camelot;555-0542
    ' z$ \) g  X$ k7 Wcore;555-2912
    ) a& _$ T9 f0 S; o/ L# r- f, efooey;555-1234! d# P$ X+ b, J  r6 e5 H
    foot;555-6699
    . f  \5 J& N# E2 Lmacfoo;555-6480; H! r( p4 E  o. b) O- X
    sdace;555-3430$ O; x  `  a2 E/ N! S3 I# ]
    sabafoo;555-2127! Q; a1 R$ w# @, o. U( W5 \+ A+ S

    . ~% J9 p" ]+ c& }4.3 printf叙述
    0 V& u4 L: h% J$ ^printf 叙述会使得输出格式较容易精确地控制。printf 叙述可以4 \) u0 ]7 ?6 w$ x$ \
    指定每个 item 印出的宽度,也可以指定数字的各种型式。* ~( r# G5 n0 F
    printf 叙述的格式如下:% Q+ H* M: K" e! X
    printf format, item1, item2, ...
    6 @2 E# g' i; j; b1 Gprint 与 printf 的差别是在於 format, printf 的引数比 print4 {; j& {0 d8 c1 [
    多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。% c  t$ Z+ }) ]' H+ [+ v1 w
    printf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙
    * l8 ~: I5 }) S; s5 _$ K1 v! Q述没有任何影响。
    5 E8 l. u* g; P8 p格式的指定以字元'%'开始,後面接著格式控制字母。
    ( N+ t5 t9 @" d! _1 H+ d格式控制字母如下所示:% h6 Y5 `( V3 ^8 X1 J
    'c' 将数字以 ASCII 字元印出。
    4 c# C. D' F5 o8 p* c3 O例如'printf "%C",65'会印出字元'A'。
    ) ^  @( V& K1 e'd' 印出十进位的整数。6 A; ^! r" g0 h) m7 C+ ?
    'i' 印出十进位的整数。' i6 J+ F7 g$ n+ _* x
    'e' 将数字以科学符号的形式印出。9 f' }& h0 x- Z& B
    例如( c; M  K2 U* N/ k' }. ]: s1 i
    print "$4.3e",1950
    0 t: m" Z5 E2 ^: h9 x' m8 U# U% R结果会印出'1.950e+03'。
    ; w0 ~4 F9 r/ I5 [7 }'f' 将数字以浮点的形式印出。; }( M+ Z4 J2 R+ |/ ]' B
    'g' 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果
    & |6 C$ f1 ^0 x8 x9 Z* z大於等於0.0001则以浮点的形式印出,否则以科学符号的形式印
    1 \% K: {% s; w出。
    ) W- z' H$ [$ \0 E! i'o' 印出无号的八进位整数。% `9 E0 w8 ~: N9 R5 b+ p
    's' 印出一个字串。5 H3 k4 J& ^) e. O; e6 u
    'x' 印出无号的十六进位整数。10至15以'a'至'f'表示。6 p! G* f- ^+ [% F- ]! m
    'X' 印出无号的十六进位整数。10至15以'A'至'F"表示。2 v2 I+ G0 L( Z; f
    '%' 它并不是真正的格式控制字母,'%%"将印出"%'。# |- V: M1 D- _) y
    在 % 与格式控制字母之间可加入 modifier,modifier 是用来进一: c" N( _& F8 J8 n3 [
    步控制输出的格式。可能的 modifier 如下所示:9 w7 n6 h( k( K, P9 q
    '-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在: w3 h4 X# ]  M: V$ H8 ~
    被指定的宽度向右靠齐。例如:
    0 i( N- @4 K. yprintf "%-4S", "foo"
    : [: D5 ?5 i& u$ f( V会印出'foo '。
    6 \: K, h$ u0 d9 c7 l# F'width' 这一个数字指示相对应的栏位印出时的宽度。例如:% N* J' y" b* K7 C0 x) M% P( Q; ~
    printf "%4s","foo"
    9 h5 B! j' {8 K. H* v. E/ h9 n会印出' foo'。9 p- p/ p) F* P( j: ^
    width 的值是一个最小宽度而非最大宽度。如果一个 item 的
    ! }/ y0 l& R3 I值需要的宽度比 width 大,则不受 width 的影响。例如* [5 O1 |- s! ?6 X- b  o
    printf "%4s","foobar"
    3 j3 E+ M& [. J将印出'foobar'。
    ; [2 x( O2 X" K'.prec' 此数字指定印出时的精确度。它指定小数点右边的位数。如3 ~* Q7 d5 t9 ^, C6 q+ q0 Z  B; _
    果是要印出一个字串,它指定此字串最多会被印出多少个字$ G" H& ^3 G9 l8 x
    元。9 P: s# r1 g. r/ w1 W
    ' j6 W' V" A# o
    第五章 patterns
    . M0 ^7 O# S. f% H$ Z在 gawk 程式里面,当 pattern 符合现在的输入记录(record),其$ @6 p) a& J8 H! t8 w* ]
    相对应的 action 才会被执行。
    ! {) s1 U" t7 w7 k" y( w* [
    4 c" O' S. ^- Y- K$ M3 a5.1 Pattern的种类
    ) M8 C8 O( z. D9 ~/ O6 Q$ H( G$ L这里对 gawk 的各种 pattern 型式作一整理:
    0 U" z1 y: c$ w& i6 Q5 V/regular expression/
      Y- ^) J/ R. |; Y一个 regular expression 当作一个 pattern。每当输入记录 (
    + r$ `; r* b/ K* Yrecord)含有 regular expression 就视为符合。& H* \  U5 N  v- C. p. q2 ]
    expression
    : Y  r- ~5 a0 u) r$ P4 j; Y一个单一的 expression。当一个值不为 0 或一个字串不是空的,- V& [& V% M0 i" s
    则可视为符合。
    ! o5 s8 p" B+ w6 m  ypat1,pat2
    6 o8 B4 _  E0 x# R1 T一对的 patterns 以逗号分开,指定记录的□围。
    4 Q1 M/ v' J2 T" G5 CBEGIN; O2 L! Y5 |% U( c2 U; R
    END/ ^( y/ r% L5 S5 B$ v
    这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相
    : R" O. A! @8 t# |$ m3 x对应於BEGIN或END的 action。
      a- z6 J# T9 Anull
    ' \2 J& C7 j, t0 i( i这是一个空的pattern,对於每个输入记录皆视为符合pattern。
    1 J% E- W9 Q- z% u5 }2 i5 E0 o( i. y/ y1 V* S6 F; g- n
    5.2 Regular Expressions当作Patterns9 P7 {! z; {) J& z! B9 h+ r
    一个 regular expression 可简写为 regexp,是一种描述字串的方7 }# r7 F0 d) Y, Y. T! W
    法。一个 regular expression 以斜线('/')包围当作 gawk 的 pattern。; m! d$ D4 ^- H
    如果输入记录含有 regexp 就视为符合。例如:pattern 为 /foo/,
    1 }) s3 N; q1 L6 D2 a" |4 N对於任何输入记录含有'foo'则视为符合。  r* Z$ T' t5 Q' a+ n3 Z2 S
    下面的例子会将含有'foo'的输入记录之第2个栏位印出。4 {* i% L7 J' W9 L
    gawk '/foo/ {print $2}' BBS-list) U% ?# f1 d4 \' e) T
    结果如下:- v) j  j4 |5 Z/ p6 r, a$ Q
    555-12340 q  a0 I2 J  {9 U2 x) h, g; d" a
    555-6699
    7 w/ x5 u! w& J# E% V( t555-6480
    0 S3 c# d0 Z2 f+ C  w9 k. q. N' ]555-2127
    , h. t2 V6 y: I4 Rregexp 也能使用在比较的算式。
    5 I% M! T" A; Q3 G6 K/ aexp ~ /regexp/
    ' S2 o7 s2 ]% N9 s; Y6 W6 O如果 exp 符合 regexp,则结果为真(true)。: z& q+ D: m! w
    exp !~ /regexp/
    . w8 \& P3 Z2 m' k2 J如果 exp 不符合 regexp,则结果为真。8 C) f9 p* H6 U: I
    % W$ p" W. t8 s% g' i. g
    5.3 比较的算式当作Patterns
    4 l% v, J# h1 ]. U9 `比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於% H. z! X9 g3 Y. m
    、小於。下面列出一些比较的pattern:; M* g# z! \+ C5 ?3 C
    x<y 如果 x 小於 y,则结果为真。
    * r0 k& C' J- fx<=y 如果 x 小於、等於 y,则结果为真。8 m  o' D3 y. ~& p- i) d- C0 R
    x>y 如果 x 大於 y,则结果为真。
    / a  f* n" z9 y" I/ ]( Yx>=y 如果 x 大於、等於 y,则结果为真。
    5 Y0 p: H4 Z$ u) U2 L  {x==y 如果 x 等於 y,则结果为真。% e$ z: g' }) y2 ]$ j8 E
    x!=y 如果 x 不等於 y,则结果为真。+ a/ {' T* |" W6 ~0 r
    x~y 如果 x 符合 regular expression y,则结果为真。
    ( D- s* K4 r" Z* z: ]8 qx!~y 如果 x 不符合 regular expression y,则结果为真。2 R% X* V% H& r% ^5 d( G) S/ k
    上面所提到的 x 与 y,如果二者皆是数字则视为数字之间的比较,- S5 s. Y2 c/ Q5 C' _/ f- x
    否则它们会被转换成字串且以字串的形式做比较。两个字串的比较,
    7 L1 `& ?) u: c会先比较第一个字元,然後比较第二个字元,依此类推,直到有不同! s2 K8 u0 [/ ^, k0 |; y5 b
    的地方出现为止。如果两个字串在较短的一个结束之前是相等,则视5 y* l/ F. r5 j+ P
    为长的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。6 L$ r" T8 a5 ]$ p) L
    , `& s. k+ j  U9 O5 C5 `" X* p8 P* g
    5.4 使用布林运算的Patterns
    2 q4 }. \! H0 y6 J一个布林(boolean) pattern 是使用布林运算"或"('||'),"及"
    & ?) ^' \% j* D  K('&&'),"反"('!')来组合其它的pattern。
    & a0 J* o8 W8 {; y! ]3 i例如:8 O9 k( d3 H6 {4 t% f/ v1 T
    gawk '/2400/ && /foo/' BBS-list
    : \6 \4 o# d; s* v/ P# ]gawk '/2400/ || /foo/' BBS-list8 {3 V, H2 D! u
    gawk '! /foo/' BBS-list
    ( w0 O: p4 ]& W, p( Q- z1 q$ F3 k2 X% f3 ~1 z# @; o
    第六章 算式(Expression)作为Actions的叙述
    + d/ J- }7 c5 d: f9 ^2 X! X算式(Expression) 是gawk程式里面action的基本构成者。
    1 c: A; O; P9 j. u3 _6 g5 M5 J4 ~
    1 C- I1 p: x0 y6.1 算术运算8 \( T% C& [$ d) a4 T
    gawk 里的算术运算如下所示:
    " M9 ~' r! T2 C  Y* |3 N; |. ~- f, @x+y 加5 w+ B& P( a6 }3 Q2 V+ P2 o
    x-y 减1 p6 w( Z6 z) J4 z
    -x 负! I  y- ^; O1 ]1 h( J
    +x 正。实际上没有任何影响。
    + x# G' G& |. A; d! kx*y 乘
    1 c& U4 L3 }: i0 zx/y 除" S9 T( `' b) f; Z. Q
    x%y 求馀数。例如 5%3=2。
    - B  o8 _$ }1 f! gx^y
    / s$ p: ~' i9 S5 g2 r' S4 h7 h1 H8 V" rx**y x 的 y 次方。例如2^3=8。
    , f  a) D. Z# g6 ]! P% h5 D% A& e  U/ F% K2 ?/ t' @+ |$ |
    6.2 比较算式与布林算式) E1 s$ h- A$ j$ h- ]( R  A
    比较算式 (comparison expression) 用来比较字串或数字的关系0 L1 o9 s0 {( ?. ]0 p
    ,运算符号与 C 语言相同。表列如下:
    0 t; W1 ~: w' C( D. F2 B$ f1 Xx<y
    - c  i+ }% M) p; j# J) Mx<=y
    $ N1 _8 K* t; |2 C; j1 ax>y9 I4 H/ m% ^6 n4 o0 t  J& [
    x>=y2 K2 w( b% N# h* x, \
    x==y
    : ?, n% p& i3 r& h1 E! O! Sx!=y. H0 X5 Z3 l8 d, E
    x~y6 H: A; p; Y! i9 J1 t0 y5 c4 X
    x!~y
    4 w5 a' Y) U; [) l! C比较的结果为真(true)则其值是 1。否则其值是 0。
    ) M& W. h  o( g0 A布林算式(boolean expression)有下面三种:
    4 ~8 b0 k- R( J- Dboolean1 && boolean2- U! N4 A( L9 Z- s1 F  r- E& c3 i$ M
    boolean1 || boolean2
    + A/ b1 p% X  c8 n5 e7 a! Q' E7 q! boolean
    : F9 x( ~+ {! a/ Z- g7 D
    / q6 m, [9 }  O, S" O6.3 条件算式(Conditional Expressions)
    # h5 {* l1 p* m( c; _, L一个条件式算式是一种特别的算式,它含有3个运算元。1 o% i8 L3 Y8 Q" R
    条件式算式与C语言的相同:: o  q7 M. t2 ^# Z, {8 N
    selector ? if-true-exp : if-false-exp
    5 }' g9 J, ]8 Q; @它有3个子算式。第一个子算式selector 首先会被计算。如果是真,! b2 j! I& U. W* T
    则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-' E& s' l6 m  j
    exp 会被计算且它的值变成整个算式的值。( J% u1 a+ |7 q. T( f3 `% M
    例如下面的例子会产生x的绝对值:
    8 h9 g: N+ ]% ~. ~, Ix>0 ? x : -x( r* q( X/ V: F' N( U: b1 p& t9 _

    : d1 }$ k4 A, s. [第七章 Actions里面的控制叙述
    - E% f- `$ j, F) ^4 ~& Q* `$ E在 gawk 程式里面,控制叙述诸如 if、while 等控制程式执行的流( f4 B$ b$ k: U& R
    程。在 gawk 里的控制叙述与 C 的类似。8 Z' p5 O2 d1 |& S
    很多的控制叙述会包括其它的叙述,被包括的叙述称为 body。假
    2 [+ O2 l9 n. M如 body 里面包括一个以上的叙述,必须以大括弧 { } 将这些叙述括起
    * u  m' [# [3 U来,而各个叙述之间需以换行(newline)或分号隔开。
    / e2 ^% w' q1 F1 w9 w0 D. b. f& G$ J% g. o* C6 x
    7.1 if 叙述$ l* [! L  W* \$ B" `9 `$ b- w
    if (condition) then-body [else else-body]
    ; Y) S* Q  S* N( m2 I0 m- q如果 condition 为真(true),则执行 then-body,否则执行 else-body。
    9 \: Y# G: x# `' y, x' @举一个例子如下:1 q- A/ V; ^& `* F! x
    if (x % 2 == 0)
    / e4 `1 A! Y9 h8 _print "x is even") r. V/ S; l+ r+ o$ z
    else7 z& E/ l& J0 k# _6 ]* ^! `- @3 `6 F
    print "x is odd"1 F, G, W' w  k1 Q! C
    6 }. c7 h) T& u! ~
    7.2 while 叙述
    ! \+ a, M' k& I7 ewhile (condition)' J" y9 Z9 y" Z$ p( J
    body
    + a8 p" }6 ]0 X8 e7 b* a1 wwhile 叙述做的第一件事就是测试 condition。假如 condition 为真则
    ( a; h7 O% b9 l( ~8 q0 @8 T9 j执行 body 的叙述。body 的叙述执行完後,会再测试 condition,假如
    2 F# k. y/ D; rcondition 为真,则 body 会再度被执行。这个过程会一直被重复直到1 _: |7 P7 V- `. z! p
    condition 不再是真。如果 condition 第一次测试就是伪(false),则
    3 m5 t3 L# m& C& \+ Obody 从没有被执行。; W  e( O) f, x$ d7 a7 n# p# W
    下面的例子会印出每个输入记录(record)的前三个栏位。: V3 L( |7 B( j! f
    gawk '{ i=1
    & W+ m  V! ?  i" {( f& e; Qwhile (i <= 3) {. G* l: k+ _# K+ |
    print $i
    $ ^" Q: w- F3 ~* a( ^i++
    ; B/ l# t( w6 x$ Y# i/ y}. k2 @5 B( m3 ^5 k
    }'
    7 x+ X9 D8 b3 `% I! W" i2 K# ?3 c1 q8 I5 @6 ^2 Z
    7.3 do-while 叙述9 B" N1 d) _  Z% M
    do
    / {# R7 I) I1 C* M3 [body+ e2 J0 H9 a4 u# t
    while (condition). i% C+ {7 ]& H5 d2 a# T
    这个 do loop 执行 body 一次,然後只要 condition 是真则会重复执行 body。: e: |4 A- `' o( e
    即使开始时 condition 是伪,body 也会被执行一次。
    0 r, f' ~7 J# Z# l下面的例子会印出每个输入记录十次。
    ! X: a' L* X0 b5 X( H7 ugawk '{ i= 10 X; r8 i; P/ V/ j  `/ y
    do {
    1 B8 E: l; f2 U/ ^print $0$ T3 Q( x3 D' H$ r
    i++: H/ {) z: t& Z$ w2 }; a4 `
    } while (i <= 10)
    ) W4 a; r5 t# P0 n% y; v6 W7 V# e}'
    9 @( W' K3 |( {$ A7 t* b/ A! m$ ^; H
    7.4 for 叙述  S2 L5 e0 g" k# h& E
    for (initialization; condition; increment)& f2 l5 z( ~) C+ w
    body
    $ p9 q& i3 x4 @9 X7 a此叙述开始时会执行initialization,然後只要 condition是真,它
    . ]$ O0 b6 \0 ]" w. w会重复执行body与做increment 。$ A  g; _/ M9 `* Y' r
    下面的例子会印出每个输入记录的前三个栏位。
    3 i& i9 c+ Z1 w8 K& v4 A' ?  Q2 Hgawk '{ for (i=1; i<=3; i++)
    1 n+ C* v0 W. x, h! y& Vprint $i% G# O6 v- ]* z# n5 o$ r: e' j
    }'; h+ P1 O7 i: O- {* F

    # ?% H, K6 T  x9 j$ \3 D7.5 break 叙述0 S' P) N9 L( s# Z. d
    break 叙述会跳出包含它的 for、while、do-while 回圈的最内层。* X: J; N: ~0 |' n# V/ v$ ^1 }7 B
    下面的例子会找出任何整数的最小除数,它也会判断是否为质数。
    3 O4 E5 u  z8 X) a/ Xgawk '# find smallest divisor of num
    1 R* H/ g! F1 c) B  V{ num=$1! t. H! z, H  ^1 s* K
    for (div=2; div*div <=num; div++)' K$ _$ k, A8 C! U3 O
    if (num % div == 0)
    ( O" n# U) ]0 Y  Y; Obreak
    0 V% [" G3 @$ m4 T: Iif (num % div == 0)$ J0 O6 d5 @8 C+ g- E4 X# n
    printf "Smallest divisor of %d is %d\n", num, div: h0 x! u5 `0 i
    else7 R" ?) E3 z0 [9 o9 G! E* M" @
    printf "%d is prime\n", num }'
    - d# @" [+ u. d* D: L' M9 M6 ~3 ~5 T. o  v' c% p! [* y
    7.6 continue 叙述
    7 A) {* k3 q) L- Fcontinue 叙述使用於 for、while、do-while 回圈内部,它会跳
    6 [5 M: c* {9 @4 ?9 l% H: h3 y" M过回圈 body 的剩馀部分,使得它立刻进行下一次回圈的执行。  x) n8 B6 {7 X/ ]! U) H
    下面的例子会印出 0 至 20 的全部数字,但是 5 并不会被印出。7 u! M% n2 ?2 f3 C9 E& T' C
    gawk 'BEGIN {
    : m* r! D( P6 Pfor (x=0; x<=20; x++) {4 g2 z5 i* }: {4 Q+ M; G6 d
    if (x==5)
    ( p' |: p6 ?. ~& V# k, @continue; z  _1 u/ L: p8 C) L& T4 b/ P9 J
    printf ("%d",x)
    1 k& v4 O( Q2 q! e6 M# T% _) P' H}
    & T9 {: g+ \+ c5 Lprint ""3 B, N( L% {; l% [" i7 j2 M/ k
    }'( U5 ?/ E: W& F+ O5 q. y
    9 F% Q$ T; H4 O6 w2 R
    7.7 next 叙述、next file 叙述、exit 叙述0 l0 l: F# q, y" B0 B
    next 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一
    0 K* L9 Y/ B3 A0 h个记录。4 e0 y( @& @, J) ^0 M" ]8 L0 G" c) R( W
    next file 叙述类似 next。然而,它强迫 gawk 立刻停止处理目前
    $ d+ i5 @- ~# `/ v的资料档。
    # y. ~: ~5 u1 sexit 叙述会使得 gawk 程式停止执行而跳出。然而,如果 END 出现
    $ w3 ]7 C+ w. t,它会去执行 END 的 actions。+ m0 J1 z4 ^" {5 v

    ' M: E5 d5 k! Y+ G, s第八章 内建函式(Built-in Functions)
    0 b* x# P6 q9 l. x内建函式是 gawk 内建的函式,可在 gawk 程式的任何地方呼叫内建7 v2 `1 S- U! _) I- D/ ~
    函式。/ C, E" L& F8 {/ w7 ~

    # R/ V, t: X! e: f: ^! m' W' f# h8.1 数值方面的内建函式
    ' I  r. X7 _7 {int(x) 求出 x 的整数部份,朝向 0 的方向做舍去。例如:int(3.9)  V7 T# `5 ~  S% c0 H
    是 3,int(-3.9) 是 -3。6 g' `, Y" C7 X$ _% Z' f
    sqrt(x) 求出 x 正的平方根值。例 sqrt(4)=2
    + z5 b0 x4 [3 ^- w% O# @) Zexp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。! c- M" _, A8 E2 F# R
    log(x) 求出 x 的自然对数。
    2 E9 S4 u; l+ i$ {sin(x) 求出 x 的 sine 值,x 是弪度量。' T, I2 M# Q/ f6 _
    cos(x) 求出 x 的 cosine 值,x 是弪度量。; Q; s. ?+ g3 h% Y% j  M
    atan2(y,x) 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。
    " y% q' t& r$ z6 a$ [5 orand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个
    ) P' r6 o5 p: ^3 P5 q" m$ s' x值不会是 0,也不会是 1。) ^  J* _& o8 `  t: t8 `
    每次执行 gawk,rand 开始产生数字从相同点或 seed。' j" K/ w: F: Y5 e1 e( a
    srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设
    9 S; A8 [+ R7 J5 Z( R' R3 `定相同的 seed 值,你将再度得到相同序列的乱数值。
    ) p+ l5 b7 v3 p$ F; M如果省略引数 x,例如 srand(),则现在的日期、时间会
    ( v. H0 `' x$ b# h/ b被当成 seed。这个方法可使得乱数值是真正不可预测的。" T2 R# }3 Y5 R
    srand 的传回值(return value)是前次所设定的 seed 值。
    & N/ V. @6 P8 u0 t
    , z" U5 f) U; Z( `- O8.2 字串方面的内建函式
    ; [( b$ r& b) `1 yindex(in, find)
    9 _# p1 c" J6 i2 l- f它会在字串 in 里面,寻找字串 find 第一次出现的地方,传回值是
    , Y- U' H- a& n) {$ g9 \) r& @字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字8 d8 g% k. n! B& Q8 G* s
    串 find,则传回值为 0。
    ( f/ b0 E" }+ M例如:5 z! T6 b2 W7 Z. Y" v% s
    print index("peanut","an")
    / T# M' }' O% |7 a会印出 3。
    , }, e. |2 C$ {! V/ ^length(string)! T& {4 W9 a; _! O* F; I
    求出 string 有几个字元。
    6 p  F5 P' |2 J, R3 |$ i例如:
    / i; |' ?5 R9 m5 I- blength("abcde")1 i% W! Y, i: |/ B, L
    是 5。" {, ?) j- ^  f0 s5 ]
    match(string,regexp)9 ^- D' K0 V& _, R# N& t2 X
    match 函式会在字串 string 里面,寻找符合 regexp 的最长、最靠9 ^% ?. q8 e& e8 C
    左边的子字串。传回值是 regexp 在 string 的开始位置,即 index6 D7 Y. @- @$ n6 d$ t! V% u
    值。
    8 n% @6 d- I% u3 T8 ematch 函式会设定内在变数 RSTART 等於 index,它也会设定内在变
    5 N% d, [  P# c数 RLENGTH 等於符合的字元个数。如果不符合,则会设定 RSTART 为% G, r$ y5 p6 u/ [
    0、RLENGTH 为 -1。
    ( ]& N% j* F6 v: w+ x+ Msprintf(format,expression1,...)& _# z3 U! W- X; L
    举 printf 类似,但是 sprintf 并不印出,而是传回字串。
    0 G8 F$ s+ ]! Y- E, v8 R4 f, v/ d例如:5 {5 v$ J9 T" F; a0 |" h: }
    sprintf("pi = %.2f (approx.)',22/7)
    + Q( e3 |2 m3 Z/ h8 ]传回的字串为"pi = 3.14 (approx.)"6 n! u  j/ I0 Q2 L+ R
    sub(regexp, replacement,target)+ Q1 H0 G1 K, l
    在字串 target 里面,寻找符合 regexp 的最长、最靠左边的地方,
    . K  W, ~( S+ `以字串 replacement 代替最左边的 regexp。
    * v% E1 x1 W$ V- A9 H% i例如:' M8 u3 V$ t( G6 h2 C
    str = "water, water, everywhere"% S6 w# O$ @: r
    sub(/at/, "ith",str). ?! u9 ~8 @$ }& \
    结果字串str会变成
    7 T) R7 W+ |( u  ^* S"wither, water, everywhere"3 w4 Z" P) j/ h9 \- i1 `: d
    gsub(regexp, replacement, target), Y) h5 _1 T# @3 }
    gsub 与前面的 sub 类似。在字串 target 里面,寻找符合 regexp 的4 V* V+ y& {* M  i% q3 F
    所有地方,以字串 replacement 代替所有的 regexp。
    5 R* w$ g: i: R- F( n& Z例如:
    , F  i5 Z4 o& ]; ^6 L6 h0 nstr="water, water, everywhere"
    / e$ F9 |5 J7 w8 S6 A: a- }gsub(/at/, "ith",str)
    9 [4 ]* b2 F! X结果字串str会变成6 p& c, m* v  l" b3 B
    'wither, wither, everywhere"- O3 g& u4 ?! o
    substr(string, start, length)' w1 p2 X0 ^6 y1 G  w: C
    传回字串 string 的子字串,这个子字串的长度为 length 个字元,0 L2 O/ m) k/ y4 Q3 F& ~. Q! ~
    从第 start 个位置开始。
    8 H+ A* T/ `1 f  x9 v2 v# k) u. O( m例如:
    - I2 v* p& m/ u* y: usubstr("washington",5,3)
    7 P) D# v: Y+ R# L. t5 h& m传回值为"ing"
    6 P- B& k/ j% e  Z% o如果 length 没有出现,则传回的子字串是从第 start 个位置开始
    " ^* V) j) D, J0 i+ r3 Y) g至结束。9 L: t$ i" P7 K3 n; K/ l& o
    例如:
    4 C' a8 s! ]8 v  x: [* Dsubstr("washington",5)+ P% R) g5 G+ d* V  N. N; e
    传回值为"ington"
    ! q0 P2 C: m) z+ @tolower(string)8 c/ }: Q9 T% i  L. X/ c
    将字串string的大写字母改为小写字母。
    7 }6 }9 X1 W% r: c/ ^5 C" H. {例如:6 [: C. `; T  [. h" c" ~
    tolower("MiXeD cAsE 123"): A6 ]) {" {3 H  R2 y7 R6 K
    传回值为"mixed case 123"
    # L4 U! T% M; I, \2 ctoupper(string)% ]" H, H6 N$ j/ B; C3 T2 S5 n
    将字串string的小写字母改为大写字母。
    - X2 A% \. T  U. ]) T8 Q) `例如:" Z* u5 V) I' Q$ r3 p
    toupper("MiXeD cAsE 123")+ H0 b/ g% o' r' S' z
    传回值为"MIXED CASE 123"
    $ s) @, C2 D& e3 b6 Z' P* O- Q3 {/ y' R. G
    8.3 输入输出的内建函式0 M% [7 }' P' ?4 o" U$ c# F0 R
    close(filename)% ]  s! J6 x. Z2 W2 d! I
    将输入或输出的档案 filename 关闭。
    - ?4 N, P/ J. E4 B7 h1 H: Z, _system(command)
      i4 j  {3 t( E1 A) s2 z. [此函式允许使用者执行作业系统的指令,执行完毕後将回到 gawk8 e4 I  v8 y5 B# A2 b7 x  q
    程式。: K5 N3 Z) r5 n3 @
    例如:, h) X8 o! _+ c( x, G7 m+ \# ~1 F) |
    BEGIN {system("ls")}
    ( `) Q) g9 j+ i& e% A$ k
    6 [  p0 [5 E' s( }' V  Y第九章 使用者定义的函式(User-defined Functions)
    * i3 I" O3 a( `9 i( \复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用, s' P/ v. P, X
    者定义的函式与呼叫内建函式的方法一样。3 k7 W4 B/ ^6 j0 G
    $ H- N2 }1 c' V* a6 o, q+ w# I2 O; C
    9.1 函式定义的格式
    % Y5 I+ s% |! J. }( k: ^函式的定义可以放在 gawk 程式的任何地方。8 t- h! q0 K+ f0 s
    一个使用者定义的函式其格式如下:% V) R  }( Y# l2 j1 Z8 |0 ^
    function name (parameter-list) {
    + L; G4 B% |3 k) ]3 I% u. Bbody-of-function' t" w% J9 `9 s" i4 w6 Y4 R1 J
    }. ]. j7 n, |1 i( L
    name 是所定义的函式之名称。一个正确的函式名称可包括一序列的字
    3 N* ~/ g( U" `3 V2 x- H, [  [母、数字、下标线 (underscores),但是不可用数字做开头。( I. P; E. v; N2 D+ j4 Y
    parameter-list 是列出函式的全部引数(argument),各个引数之8 X6 g: {/ L6 s
    间以逗点隔开。
    5 P+ B) c: x# a0 D( ?' l6 @body-of-function 包含 gawk 的叙述 (statement)。它是函式定义
    , B0 M& u) r4 k3 l# A# c' h里最重要的部份,它决定函式实际要做何种事。3 s4 C1 s7 |/ N6 T" W# _6 \

    + q+ {% [/ p1 o9.2 函式定义的例子
    & g2 e1 Z* l0 n$ ]  c* y. O8 S+ P2 _- c下面这个例子,会将每个记录的第一个栏位之值的平方与第二个+ c! p5 R+ i' o& a
    栏位之值的平方加起来。
    ! @  H0 |' ^( M9 U{print "sum =",SquareSum($1,$2)}
    % J7 J$ F' r3 G4 G$ qfunction SquareSum(x,y) {
    & r; K  H) ~7 A2 T; x6 w# a2 T9 m+ wsum=x*x+y*y  a* L" x- ~( E
    return sum& \/ O1 N5 ]/ r5 o# j1 M7 |
    }
    ' L" w# @: }: ~: R, W
    6 c9 S- k* @4 c) U& s7 Z第十章 □例0 B/ ^2 e) {; r1 `: ]+ l
    这里将列出 gawk 程式的一些例子。
    $ Y( S7 q" Z" P5 bgawk '{if (NF > max) max = NF}4 L6 R6 q4 s; V& N4 b
    END {print max}'
    ' r5 d5 n# N& J5 ]* v! r此程式会印出所有输入行之中,栏位的最大个数。2 F9 _" k1 o6 @1 k: h! t( p8 {7 X; `  X( Z
    gawk 'length($0) > 80'  k6 a7 Q" n, f4 ~% w0 V8 D, ]0 \
    此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被
    ; r4 b. ?" d+ g6 O/ |列出,action 是采用内定的 print。
    $ B8 i! f7 p4 n/ S! y- P! d+ Bgawk 'NF > 0'
    5 Y, z+ A2 {* T0 b对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简
    ( |4 G1 b# |! j% [3 G% R单的方法,将一个档案里的所有空白行删除。/ n/ Y5 ]% N' N  g
    gawk '{if (NF > 0) print}'6 B, w" g& {  S
    对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简
    & U3 M, G; }2 d% Y* k) t/ {- l单的方法,将一个档案里的所有空白行删除。
      l+ [3 d) |1 _gawk 'BEGIN {for (i = 1; i <= 7; i++)( @* C7 C6 n( B* _% x
    print int(101 * rand())}'
    3 k7 U" E% j# U4 y$ @6 H此程式会印出□围是 0 到 100 之间的 7 个乱数值。: l) b$ B- I* {9 c9 |& R! @. a- A  i/ X
    ls -l files | gawk '{x += $4}; END {print "total bytes: " x}'
    0 s: X: H, \" U5 c: e此程式会印出所有指定的档案之bytes数目的总和。/ I. G/ e6 {! |1 l% F. R
    expand file | gawk '{if (x < length()) x = length()}0 p) B& z: ~. ?. r3 V
    END {print "maximum line length is " x}'
    % l: x4 [. `3 U3 ?此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改& o' q" X7 W2 S5 _% K, @
    成 space,所以是用实际的右边界来做长度的比较。
    $ u3 @" c% ?/ {/ ^: I- p! Mgawk 'BEGIN {FS = ":"}
    - L0 l' I2 }# w- ~# y' w/ ~{print $1 | "sort"}' /etc/passwd" z1 U4 X# G( \
    此程式会将所有使用者的login名称,依照字母的顺序印出。2 B" H0 J  r' _; N! V' g. X9 g1 v$ i
    gawk '{nlines++}
    9 P! w( T) P6 D# fEND {print nlines}'
    6 W$ a1 }. m" `, p& W6 g此程式会将一个档案的总行数印出。' @" z: F2 ~. F+ l
    gawk 'END {print NR}'
    6 C7 o; l: F# p2 W8 k4 Q. |+ z此程式也会将一个档案的总行数印出,但是计算行数的工作由gawk
    ) O+ D1 H+ ^# }+ g8 R来做。6 z" p# Z8 A1 G, h- [% N" B
    gawk '{print NR,$0}'4 }) Y) J3 M' L8 j% J, N+ \- s
    此程式印出档案的内容时,会在每行的最前面印出行号,它的功
    ' g$ M! r% w6 z! B: O能与 'cat -n' 类似。
    & n: B5 \0 K# A! m3 A) U9 _' n5 [* o! Z! A; y; r2 U6 y
    第十一章 结论: R/ W, F3 E. V1 H( _
    gawk 对於资料的处理具有很强的功能。它能够以很短的程式完成9 ]* s  ^. P3 \+ R7 W! a$ H5 N
    想要做的事,甚至一或二行的程式就能完成指定的工作。同样的一件
    7 D6 c7 L. S$ e  j* Q& m5 {工作,以 gawk 程式来写会比用其它程式语言来写短很多。. k- ]  E- _1 a) Z
    gawk 是 GNU 所做的 awk,它是公众软体(Public Domain) 可免费使7 a7 \; |/ R/ H% r( v
    用。
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    楼主热帖

    相关帖子

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

    该用户从未签到

    尚未签到

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

    本版积分规则

    招聘斑竹

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

    GMT+8, 2025-4-11 09:58

    Powered by Discuz! X3.5 Licensed

    © 2001-2025 Discuz! Team.

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