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

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

Gawk手册

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

    连续签到: 1 天

    [LV.1]初来乍到

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

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

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

    ×
    GAWK
    5 w% R+ L  e% i第一章 前言$ L/ y2 |6 R9 ^- L" @' X) k; k
    第二章 简介  I7 ]) B3 A5 @- u. g) \3 Y
    第三章 读取输入档案" H* J+ M: g! \- G0 b% ~
    第四章 印出; C# I& ]  J5 @# w5 _
    第五章 Patterns
    4 z4 _" y1 v, h5 |  y' ^* Y第六章 算式(Expression)作为Actions的叙述8 @2 ?3 g4 c: \. ^0 h- Y
    第七章 Actions里面的控制叙述
    7 ^2 Y! {2 P7 D6 h. y) T7 C7 y第八章 内建函式(Built-in Functions)
    6 E: Z0 ^% ~2 m第九章 使用者定义的函式
    + @2 V, g2 E! I* o' G: m) E第十章 □例, c  `* p7 t' @) U
    第十一章 结论
    ) y' F3 ?) H. K3 e. Z' R3 H3 T2 C4 U$ M& ]" M1 d8 y
    =======================================
    ( I/ D" l' i0 O- P, D7 F第一章 前言2 _' S% F: D4 {/ c; K- J9 }  u
    awk 是一个程式语言,对於资料的处理具有很强的功能。对於文: ?- C- \  ]# ]% j) v: }8 ^
    字档里的资料做修改、比对、抽取等的处理,awk 能够以很短的程式. f' |9 d. s" f  R. ?# U
    轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作,% V5 k  a+ Z2 R
    会不方便且很花费时间,所写的程式也会很大。
    0 }. a: h2 [) ~' e' rawk 能够依照使用者的定义格式来分解输入资料,也可依照使用
    - n0 z8 \' r0 n7 o; ]者定义的格式来印出资料。; e- n+ O0 |! p2 P' Y
    awk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名
    3 o. A/ _! f$ G% r:Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。+ N& a3 ~$ m+ d: J* i) N7 j4 a+ R
    awk最初在1977年完成。一个新版本的awk在1985年被发表,它的功能/ R' f( a- k+ \; b+ ]) H; a6 k$ c
    比旧版本增强不少。0 x2 Y/ ?$ n: I4 y
    gawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不断地! k, {- s: f  R# f$ j
    被改进、更新。gawk 包含 awk 的所有功能。
    8 ^  Y: v1 b6 p( `; L往後的 gawk 将以下面的2个输入档案来做例子说明。
    ) E- N; x% e) E* V8 @% o% s档案'BBS-list':- `; N% q- Y* t& g/ n2 S* A
    aardvark 555-5553 1200/300 B" o) K& I8 H6 s" Z! N
    alpo-net 555-3412 2400/1200/300 A: D2 ~5 r6 h" W. `, {6 E8 H3 k* u
    barfly 555-7685 1200/300 A4 d) p& m4 r/ p2 H& M" }8 I- E
    bites 555-1675 2400/1200/300 A
    9 w+ P* R  e! u$ _* y) `6 a2 ucamelot 555-0542 300 C1 B, \; c  Q  N
    core 555-2912 1200/300 C
    5 l( }' x' z+ Y2 O& z* L# N- ~fooey 555-1234 2400/1200/300 B
    - O8 ?4 w* T' E' W+ Ffoot 555-6699 1200/300 B* `9 B2 _2 O7 |' _, W
    macfoo 555-6480 1200/300 A+ B- S+ A: M" G" W; s* Q# d
    sdace 555-3430 2400/1200/300 A
    ; A, w. n) A% u, ?3 b8 ]. Z+ v% T3 ^sabafoo 555-2127 1200/300 C9 D3 F3 t, a9 q" e
    档案'shipped':
    - `) N" t# c% E! dJan 13 25 15 115: B: s9 `* O3 g, n
    Feb 15 32 24 226
    2 I9 W0 b. G% f: m" k8 X- @, x5 FMar 15 24 34 228! W- x2 f9 A5 w" x$ v7 V. [
    Apr 31 52 63 420$ i: `4 d3 f- E7 S- ]4 [3 n1 K
    May 16 34 29 208
    1 \6 b- L9 r/ U) }) B% eJun 31 42 75 492
    6 S+ E& `, B9 R8 [! g. RJul 24 34 67 436
    ) E# e( T4 P1 oAug 15 34 47 316
    1 o$ l* E2 G/ a) \' a# wSep 13 55 37 2778 V- l! K2 f: }+ H7 e, L* i
    Oct 29 54 68 525
    ) o- k# T- T7 M# U% ZNov 20 87 82 577+ V0 H7 ^6 N" y- S; N1 m6 j9 H' O
    Dec 17 35 61 401* S, x- a1 |1 P* b
    Jan 21 36 64 620
    9 \9 }  w/ w+ qFeb 26 58 80 652
    * r2 @! [# V3 j2 p2 b' j1 sMar 24 75 70 495: e0 d9 l6 C; ^
    Apr 21 70 74 514
    4 _' \# w# K9 s! z6 j7 M" t. j  {5 n' Z$ `, i$ r$ J8 m
    第二章 简介7 H) F# I) }( E
    gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns
    ! A2 n& k, \/ S- C; e$ c; R. c) D。当一行里有符合指定的 patterns,gawk 就会在此一行执行被指定
    ' m7 `& ?, R' @' L8 y  _的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结
    + y1 `/ c: X; k* L" p4 K& Z束。5 g' s: M- ^+ b/ V8 s
    gawk 程式是由很多的 pattern 与 action 所组成,action 写在  ^. r6 [- Q9 V3 \: p8 Z
    大括号 { } 里面,一个pattern後面就跟著一个action。整个 gawk 程
    / t1 S) E% \8 O& p- u式会像下面的样子:
    ( }/ y+ [9 y) ?$ T, ]. Bpattern {action}
    ( I. R: L/ C& ?! a3 W2 i9 ?pattern {action}' Q, j" k2 M" a
    在 gawk 程式里面的规则,pattern 或 action 能够被省略,但
    $ |% I0 ?* c$ ]8 d是两个不能同时被省略。如果 pattern 被省略,对於输入档里面的7 J8 a( V2 [5 r0 ?
    每一行,action 都会被执行。如果 action 被省略,内定的 action! h: |) G2 g; c" Y
    则会印出所有符合 pattern 的输入行。, A) Y8 ^; j. \! V1 b4 G* b

    9 u! a8 E6 k% H7 G2 r. i2 F/ p+ S2.1 如何执行gawk程式
    + Y; j5 k& B; H  q基本上,有2个方法可以执行gawk程式。
    1 c( f0 Y7 z; q0 N/ r□如果 gawk 程式很短,则 gawk 可以直接写在 command line,如下所示:+ x! [/ _7 g1 k5 V. x6 G) ~0 k
    gawk 'program' input-file1 input-file2 ...
    3 U+ O7 |8 B2 G4 Q( Z7 F6 p其中 program 包括一些 pattern 和 action。( g* @0 Z5 z! f* G% J. [  t
    □如果 gawk 程式较长,较为方便的做法是将 gawk 程式存在一个档案,! G, E, _% D: y- K: A
    即 patterns 与 actions 写在档名为 program-file 的档案里面,执行
    9 F; h9 s8 Y. m) r  q2 Ggawk 的格式如下所示:
    7 P! C) u% o, f+ Fgawk -f program-file input-file1 input-file2 ...6 c5 ]- J' T4 c- W' F  I
    gawk 程式的档案不止一个时,执行gawk 的格式如下所示:
    . h8 {% e7 O: a% j) Dgawk -f program-file1 -f program-file2 ... input-file1% J. A  N( D( o3 h$ }, Y. u/ Q4 b
    input-file2 ...
    . }! h* B1 H/ t+ W
    7 |! M& R* L& y6 {5 u, r" a2.2 一个简单的例子
    ! j0 b' q( o/ W/ n! D4 g现在我们举一个简单的例子,因为 gawk 程式很短,所以将 gawk 程" P5 }) j# Z1 D2 j  h: B
    式直接写在 command line。$ j, g0 z( U- d0 U5 _7 Y3 f, K
    gawk '/foo/ {print $0}' BBS-list/ f* b$ q. v* L3 g
    实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern,意思为搜. L- E$ R- @6 U+ m* [
    寻输入档里的每一行是否含有子字串 'foo',如果含有 'foo' 则执行 action。6 g' H" n" [; S/ Q2 M0 e3 I4 P: ~
    action 为 print $0,是将现在这一行的内容印出。BBS-list 是输入的档案。
    0 F9 o- U* V1 ^$ p执行完上述指令後,会印出下面的结果:) Y# N+ ^' {& ^# U. M% c) r$ _
    fooey 555-1234 2400/1200/300 B; Y) M4 s5 S9 R! R" i9 c& ~. A2 K
    foot 555-6699 1200/300 B
    4 r- Z4 y- D8 g) |; pmacfoo 555-6480 1200/300 A
    / h. }# t$ m: a" c0 \6 msabafoo 555-2127 1200/300 C$ N1 i+ g/ M" j% x

    4 X+ n4 A6 u3 ?4 e2.3 一个较复杂的例子/ e* ^5 c% f2 R5 ~& S4 S. d; G
    gawk '$1 == "Feb" {sum=$2+$3} END {print sum}' shipped/ x2 P( Z  X; D! Z, q( J& X! x
    现在这个例子会将输入档 'shipped' 的第一个栏位与 "Feb" 做比较8 ?7 ?5 P' @; M0 D
    ,如果相等,则其对应的第2栏位与第3栏位的值会被加到变数 sum。) s& c1 l/ T9 _) u" a! W
    对於输入档的每一行重复上述的动作,直到输入档的每一行都被处理
    9 K( I; i3 Y7 s* H1 E" b" k) ?: D过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输
    3 ?/ k/ i- d$ M2 J8 L1 v9 N入读完之後,执行一次 print sum 的动作,也就是把 sum 的值印出。
    . Q0 M" [) X( t# e下面是执行的结果:8 b$ g0 Q( S! k
    84, Y9 @( a6 E& a7 {

    8 ?6 Z2 z' b0 p5 }1 H# ~第三章 读取输入档案. f$ A% ?4 W  F: V& ~8 ^" Z
    gawk的输入可以从标准输入或指定的档案里读取。输入的读取单  |2 c$ n: L: `+ C+ `7 w' a
    位被称为”记录”(records),gawk 在做处理时,是一个记录一个记
    * Q+ E9 G4 K  l  ?录地处理。每个记录的内定值是一行(line),一个记录又被分为多个1 h  e$ _& g0 c4 N% o
    栏位(fields)。
    * o* X  D' E6 i3 Y7 n4 k( n( |- s% |, A$ E
    3.1 如何将输入分解成记录(records)! f5 M5 t* [. ]1 \/ f
    gawk 语言会把输入分解成记录(record)。记录与记录之间是以
    ; _/ d' T0 E: }! _" ~- F* {record separator 隔开,record separator 的内定值是表示新一行的
    7 ^3 M) S/ C0 F  M: i- S字元(newline character),因此内定的 record separator 使得文字6 f6 N8 p' c* r
    的每一行是一个记录。' c1 _- g; r9 H: P4 ]  j) l; \5 ?
    record separator 随著内建变数 RS 的改变而改变。RS 是一个字串,
    3 b: v  h3 Y) {3 f它的内定值是"\n"。仅有 RS 的第一个字元是有效的,它被当作 record  h3 f8 m! _; k9 l0 k
    separator,而 RS 的其它字元会被忽略。
    5 Y8 f8 G1 C4 H9 w/ n$ _4 b内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内
    # k) w: _) E1 j  d建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。
    8 k7 B! Y; G8 M; q# G
    0 o  H. B# A4 G1 N3.2 栏位(field): d% C) l, D, ~
    gawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一
    2 B  a- j/ t* K- [. z行里面,gawk 的内定动作会认为栏位之间是以 whitespace 分开。在6 P$ K6 W& U/ ^5 [: c
    gawk 里,whitespace 的意思是一个或多个空白或 tabs。
    : M9 Y+ x% ~  h) _# ?在 gawk 程式里面,以'$1'表示第一个栏位,'$2'表示第二个栏位
    & G) l3 _- @" r- t$ z5 B7 O. `  V5 H,依此类推。举个例子,假设输入的一行如下所示:
    4 k2 I" g8 O. z$ ]# TThis seems like a pretty nice example.2 k) j. u) n# x
    第一个栏位或 $1 是'This',第二个栏位或 $2 是 'seems',依此类推。
    : B* G9 P7 c% C- u1 M有个地方值得特别注意,第七个栏位或 $7 是'example.'而非'example'。
    # q: b! G8 P- V7 `# R& F1 ~不论有多少栏位,$NF 可用来表示一个记录的最後一个栏位。以
    7 i# ]( }( N3 i% c. }7 S上面的例子为例,$NF 与 $7 相同,也就是'example.'。
    1 I" o9 |% T6 _NF 是一个内建变数,它的值表示目前这个记录之栏位的个数。3 f0 x! ~+ ~: y
    $0,看起来好像是第零个栏位,它是一个特例,它表示整个记录。1 I0 z+ z9 p7 Y) p$ r  \+ H7 V% m
    下面是一个较复杂的例子:$ @# O# Z" D  w& k7 x: L
    gawk '$1~/foo/ {print $0}' BBS-list
    8 x. F* B% ~# i: f结果如下:
    5 [8 @! o9 C3 P- W1 ofooey 555-1234 2400/1200/300 B% s3 G8 D  c7 e4 @9 a7 d& Z
    foot 555-6699 1200/300 B, l. o/ y9 D4 _$ e
    macfoo 555-6480 1200/300 A: r" T/ G: k! j5 `2 J0 }
    sabafoo 555-2127 1200/300 C
    % z7 N3 e$ a$ W" L* j( n这个例子是把输入档'BBS-list'的每个记录的第一个栏位作检查,如
    . y5 Y7 v! n2 s2 N果它含有子字串'foo',则这一个记录会被印出。
    : Y, v7 ^# O# W( B7 T4 y
    8 W5 p' i: T. k& ?+ z, i' ]3.3 如何将记录分解成栏位& ^- n  Q9 `  p  h
    gawk 根据 field separator 将一个记录分解成栏位。field sepa-4 q% ?( N8 ]- F" x
    rator 以内建变数 FS 表示。
    ! E* P( K2 W. c; ~& Y9 d举个例子,假如 field separator 是'oo',则下面的行:
    : h7 H) `! c' e) _6 w$ |moo goo gai pan
    ( I5 C9 ]! t% G$ c8 K, b会被分成三个栏位:'m'、' g'、' gai pan'。
    , k& ~0 `, u9 W/ l( O8 w- ]  f在 gawk 程式里,可以使用'='来改变 FS 的值。例如:! {. p7 j& X* L* M7 {* V
    gawk 'BEGIN {FS=","}; {print $2}'- L) ]1 P1 `, y4 j! y/ h
    输入行如下:3 N) g- M1 C( `7 x! x
    John Q. Smith, 29 Oak St., Walamazoo, MI 421395 r9 M+ s1 c  N/ O& O+ i
    执行gawk的结果将印出字串 ' 29 Oak St.'。BEGIN 後面的 action 会在
    4 i7 e0 P4 w/ l9 u, v第一个记录被读取之前执行一次。( s+ w% U  q. e: |
    ; i; }4 z3 \0 ~5 A
    第四章 印出
    - N! a" M4 m" [$ m/ g在gawk程式里,actions 最常做的事就是印出(printing)。简单) x1 r2 E  R+ l9 U+ w& W
    的印出,使用 printe叙述。复杂格式的印出,使用 printf 叙述。
    ) j  a+ X: Q, Z3 N. L% ^& u* {" Y" ]! ]& t: @- A
    4.1 print叙述. [* n3 z/ B1 g" v/ d6 D, H2 N3 }
    print 叙述用在简单、标准的输出格式。叙述的格式如下所示:1 M2 Q3 H0 \9 Q
    print item1, item2, ...: \' b& G8 L, H# P0 w0 f% R
    输出时,各个 item 之间会以一个空白分开,最後会换行(newline)。4 o$ T* J* g# u/ \' G* v0 M
    如果 'print'叙述之後没有跟著任何东西,它与'print $0'的效6 _4 J* p6 {, p% p% c* _( o6 y
    果一样,它会印出现在的记录(record)。要印出空白行可使用'print
    4 G* J6 I- X' r) L7 G""'。 印出一段固定的文字,可用双引号将文字的两边括起来,例如. d3 a/ U2 b6 R8 s- M7 x
    'print "Hello there"'。/ P& C& Y0 I( g1 l) s4 p0 D7 a' R
    这里是一个例子,它会把每个输入记录的前二个栏位印出:
    3 z+ `9 W9 W5 t8 e! I# pgawk '{print $1,$2}' shipped* u, d7 x& l0 \0 ]" r
    结果如下所示:9 i' G9 Z2 P( B* O% P+ C
    Jan 130 n$ x! n# A  I. x4 V) h# Q) j
    Feb 15
    , c3 b; g3 ?+ qMar 15) N3 ^7 l; B3 r  W; c7 W4 e
    Apr 31" R. L; r, `- _, D0 B: q, D* H
    May 167 y7 ~+ u" n3 V; b! q7 j" ^
    Jun 31
    0 U* J7 a* s7 v& rJul 24
    ; Z" e% f5 G; HAug 15  U& ?+ f+ B) A
    Sep 13
    & \% x5 }  ^: mOct 29
    2 _" v1 K" U. ANov 20. s# q' V* e; v* J, B" H
    Dec 17
    2 |9 [% @6 j# ]- ^5 u4 j, n! F) }Jan 21
    + ~6 {3 {: l: E( }; g: x1 bFeb 268 X1 B/ M4 h2 w: s- c) h: b
    Mar 24
      X' g! Q) Q5 c! W& [& Q5 CApr 21/ w% K$ }# d. g4 @

    4 d$ K4 m! I* P0 N4.2 Output Separators
    0 |$ d/ _% q3 G( ?) `/ A前面我们已提过如果 print 叙述包含有多个 item,item 之间, S' u! ?! S8 S! n2 B* K
    用逗点分开,则印出时各个item会被一个空白隔开。你能够使用任何6 N3 N' f7 d* M. S7 P; k! P6 z
    的字串作为 output field separator,可以经由内建变数 OFS 的设
    & o9 ^( E% w. z( h) E$ V* a1 P定来更改 output field separator。OFS 的初始值为" ",即一格的
    3 q6 r. W! Q* {" R. G- f' N' e$ o空白。
    . Q, B2 w* _/ I8 d7 b整个 print 叙述的输出被称为 output record。print 叙述输
    / ~0 \  ^. [/ o! a( p' M出 output record 之後,会接著输出一个字串,此字串称为 output% I+ V9 p) z' \. }* J% e3 m
    record separator。内建变数 ORS 用来指明此字串。ORS 的初始值
    2 o1 \3 s1 V" l为 "\n",也就是换行。
      e1 [! p: i, K/ ]下面这个例子会印出每个记录的第一个栏位和第二个栏位,此二. c! G% T: D$ p' x
    个栏位之间以分号';'分开,每行输出之後会加入一个空白行。; c5 P1 s8 Y+ D7 p$ B
    gawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list8 h7 N- E( ~5 R/ D7 Y
    结果如下所示:
    , _# B' H6 s7 q/ m! N" [aardvark;555-55531 P1 j8 T% s" b
    alpo-net;555-34122 B5 y7 ?! ^2 M5 @0 i9 n' z4 O  O
    barfly;555-7685! T0 }$ w& m/ T/ E8 y
    bites;555-1675
    2 b6 F1 k9 J  J" O* Qcamelot;555-0542# ^0 o' f: Z/ [: T
    core;555-2912
    6 {1 u% x* d! Z/ {1 m$ w6 J. Lfooey;555-1234
    . u7 J$ N% [0 E3 j- A7 U3 x) cfoot;555-6699. c! k, ?; H" `
    macfoo;555-6480
    $ s0 a/ O, L% w+ j; ysdace;555-34301 b$ J9 Z5 W! n, N. Y
    sabafoo;555-2127
    ' Y2 N* F7 A# V# y4 v, }3 c( z$ C1 K, K+ t7 g& X) p& p* O
    4.3 printf叙述- w1 M3 t8 l; O' W( }: {
    printf 叙述会使得输出格式较容易精确地控制。printf 叙述可以7 O: `3 w3 d& \9 M' t, p
    指定每个 item 印出的宽度,也可以指定数字的各种型式。! s2 J) P' A# j  b4 C: E9 V
    printf 叙述的格式如下:
    - W: i& K5 j) N# g( }printf format, item1, item2, ...
    9 `8 S2 G0 [  q8 V( `6 g4 j3 [print 与 printf 的差别是在於 format, printf 的引数比 print" b+ b- z8 x5 J+ ^4 j' Q- M
    多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。& u- ^  W4 L+ K/ Q
    printf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙- ?) A  g, k7 x
    述没有任何影响。
    : v  s6 ]2 {7 U8 ]  E格式的指定以字元'%'开始,後面接著格式控制字母。
    ! d  x3 R1 t+ Z5 `9 ~4 X' j5 {格式控制字母如下所示:3 C( _1 _0 ?3 @8 c
    'c' 将数字以 ASCII 字元印出。3 i" \# w6 u& G: Y( y$ b
    例如'printf "%C",65'会印出字元'A'。7 x; R; k& ]) i& f0 h, v' b5 p) H
    'd' 印出十进位的整数。- r" \# V( b6 p% b
    'i' 印出十进位的整数。
    0 M; D$ d! W2 v1 n/ c'e' 将数字以科学符号的形式印出。
    0 T8 J2 O. V% K3 \) g) H8 R! X7 l例如! C* J9 I, ^; k& V5 i
    print "$4.3e",19507 y' `9 M# a0 ^4 Y2 F
    结果会印出'1.950e+03'。" ^7 t' c$ E3 ?9 Q
    'f' 将数字以浮点的形式印出。+ J1 v" y4 @0 V) T: g1 o
    'g' 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果
    ( u  Z/ T- ^1 J7 A. |7 z& {" C大於等於0.0001则以浮点的形式印出,否则以科学符号的形式印( z; x: }8 Q7 X0 B' U3 o! V4 ^4 d
    出。  |0 q- ~% i* ^8 K, z
    'o' 印出无号的八进位整数。
    4 x9 B# ?( L6 o2 G( j" l's' 印出一个字串。' t7 A2 T& I1 }5 i8 @, Y; |( k
    'x' 印出无号的十六进位整数。10至15以'a'至'f'表示。
    " `- {8 Y! D* [7 Y" T'X' 印出无号的十六进位整数。10至15以'A'至'F"表示。
    2 g$ K0 |, ]& B0 F* a% a9 Z'%' 它并不是真正的格式控制字母,'%%"将印出"%'。# o% |$ D2 p! S; o; h
    在 % 与格式控制字母之间可加入 modifier,modifier 是用来进一* W" j5 n# F: E# ]0 M
    步控制输出的格式。可能的 modifier 如下所示:2 n3 W1 K* y8 S. e4 k3 E* u
    '-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在
    ( \4 H1 B+ I' o! J# u6 p被指定的宽度向右靠齐。例如:
    5 t$ J, @- n, R: G% I2 f- Z$ Dprintf "%-4S", "foo"" L6 Y- F' X6 z  K! c; x' ^
    会印出'foo '。
    ( A% y8 o/ ~  K8 u: x'width' 这一个数字指示相对应的栏位印出时的宽度。例如:& v  I3 B6 s, j  r7 B$ l2 }1 a
    printf "%4s","foo"9 @9 Z" b2 V! m3 L
    会印出' foo'。3 v# t0 Z1 G' `/ [
    width 的值是一个最小宽度而非最大宽度。如果一个 item 的
    * r3 j$ L$ `! D+ p* o2 C值需要的宽度比 width 大,则不受 width 的影响。例如
    1 w0 k/ \) t0 G' ]. Nprintf "%4s","foobar": X4 K; B+ \$ H6 z* W5 Z2 q
    将印出'foobar'。+ [# L! u+ ?% g/ V$ U
    '.prec' 此数字指定印出时的精确度。它指定小数点右边的位数。如
    8 h% t/ f' e+ }3 d9 |, c果是要印出一个字串,它指定此字串最多会被印出多少个字" U$ d  d" |1 M0 x* |
    元。
    ( |( N' V& x- f
    4 I$ l2 w4 S: i" F" Y' r  M/ s) i第五章 patterns
    / j  s; C/ n) @, Y在 gawk 程式里面,当 pattern 符合现在的输入记录(record),其
    0 g$ ?: J2 Z0 ^相对应的 action 才会被执行。# a% l; s( J9 \- `9 I3 a% W
    " M5 g! y/ z8 d. r% K" C
    5.1 Pattern的种类
    5 w8 \0 C, `6 R3 ^这里对 gawk 的各种 pattern 型式作一整理:
    % @) Z$ D. g% f/regular expression/
    - N! w5 {5 i7 `* I5 u8 r一个 regular expression 当作一个 pattern。每当输入记录 (
    ( F: \) E$ R0 a4 h# M* ^3 R6 urecord)含有 regular expression 就视为符合。
    0 p+ m1 O5 t/ i! vexpression) F: k0 a' u- T( d7 X  b, s
    一个单一的 expression。当一个值不为 0 或一个字串不是空的,
    9 J& @0 H0 A* J" F# q5 x则可视为符合。# Q' y6 ]3 Q! G! W# [
    pat1,pat26 E1 N/ p8 \' z4 C7 e" q; d: f& x$ i2 c
    一对的 patterns 以逗号分开,指定记录的□围。0 }$ r3 Z/ A# p' u. j
    BEGIN3 N0 F* X/ b8 X* g  s3 a
    END
    7 ]$ |4 V+ [! |/ y; x6 j/ {这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相  ?7 Z9 o' ~$ P/ P; L0 Z8 }
    对应於BEGIN或END的 action。; l, I8 _6 h/ h+ u. }
    null
    4 b# m7 k5 F0 w+ @8 h+ L4 Z* o- p这是一个空的pattern,对於每个输入记录皆视为符合pattern。7 e9 |2 N$ i0 T6 N, ?- B
    ; W) [! I, E$ V; j8 B( C
    5.2 Regular Expressions当作Patterns
    8 x  C) e6 }& D  ^& ]- w一个 regular expression 可简写为 regexp,是一种描述字串的方
    ! ^/ Y+ Y7 K; x法。一个 regular expression 以斜线('/')包围当作 gawk 的 pattern。3 J3 x: s- B. j4 b+ g8 N2 q: z
    如果输入记录含有 regexp 就视为符合。例如:pattern 为 /foo/,7 ?3 s3 W5 I# F( Y  ?: d9 h7 I+ R# \
    对於任何输入记录含有'foo'则视为符合。: k8 q, k( C- y0 E9 t4 t0 |2 i
    下面的例子会将含有'foo'的输入记录之第2个栏位印出。+ j" z- v( s  E/ ~' b! R8 K
    gawk '/foo/ {print $2}' BBS-list
    . ~& L5 U* C0 o1 P/ \( k: T/ p结果如下:
    6 ~3 H- Z, X$ D: D0 [555-1234
    * m6 E; P. K! r5 _555-6699
    % {, Y+ A6 C+ O$ b, F) Y4 v! l- u555-64809 D. I% M8 r6 d; e  g- H, D7 b
    555-21275 c# ~4 q4 _& E8 s% h, b
    regexp 也能使用在比较的算式。! u: j1 B0 ~' t# I/ f5 a1 b
    exp ~ /regexp/' X" p" A# Z" U) E" A0 s- a2 l
    如果 exp 符合 regexp,则结果为真(true)。* H* }/ |  `# p- q: q/ e% k) `
    exp !~ /regexp/
    5 y4 F& J# ~7 ^5 k1 w. o) |& X如果 exp 不符合 regexp,则结果为真。
    8 Z* d6 Z7 B% L5 y6 _. m7 `: Y0 d6 L  A( z" ~/ ~
    5.3 比较的算式当作Patterns- Z# q. L8 ?! ]6 P' \
    比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於
    & `, t& r4 A' C2 M3 w、小於。下面列出一些比较的pattern:
    9 J  c1 ^& z- X! \  y/ {x<y 如果 x 小於 y,则结果为真。( v- \# I, v6 h+ }8 d
    x<=y 如果 x 小於、等於 y,则结果为真。
    1 _. [* j' b" e1 M& Kx>y 如果 x 大於 y,则结果为真。+ T; K3 m$ Q0 J2 D: G& Y; h
    x>=y 如果 x 大於、等於 y,则结果为真。3 Y- l7 @5 {3 ^7 }* ^  {
    x==y 如果 x 等於 y,则结果为真。5 _) E3 C1 c! \1 B* p* k
    x!=y 如果 x 不等於 y,则结果为真。
    9 L! E8 h: k- W. l9 lx~y 如果 x 符合 regular expression y,则结果为真。
    / P* u% S% a7 W$ ^3 d4 ]x!~y 如果 x 不符合 regular expression y,则结果为真。
    / T2 ~: X9 R5 E% ]0 F7 G" I/ Q上面所提到的 x 与 y,如果二者皆是数字则视为数字之间的比较,
    # x. j# |: _! M* R, q否则它们会被转换成字串且以字串的形式做比较。两个字串的比较,
    $ h' h& x+ P: P! n6 h) ^8 A会先比较第一个字元,然後比较第二个字元,依此类推,直到有不同
    ( F7 a; b. e+ S6 V- \的地方出现为止。如果两个字串在较短的一个结束之前是相等,则视4 X) y/ W0 m6 l9 w7 B4 ~) F0 [
    为长的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。
    5 O# `, b* D" ?9 Z9 f: _
    % Q+ o8 E% `; T7 e5.4 使用布林运算的Patterns; C  D% ^: Z' [
    一个布林(boolean) pattern 是使用布林运算"或"('||'),"及"
    3 `6 y* G6 l" ^- c3 b/ Y('&&'),"反"('!')来组合其它的pattern。7 S& R) X' f: z! q/ V( [' T( p
    例如:
    / A7 A, H5 B6 \. H+ H! `6 Fgawk '/2400/ && /foo/' BBS-list- u5 |2 y3 H  \
    gawk '/2400/ || /foo/' BBS-list
    0 r* S$ ^# ?5 l9 L$ S- ~gawk '! /foo/' BBS-list- O8 ~" y2 y; S! f* z' t% j
    % Z9 x! s7 N" r% C8 _3 t$ _5 g! u" ~
    第六章 算式(Expression)作为Actions的叙述2 Q9 `+ O* z. P- a
    算式(Expression) 是gawk程式里面action的基本构成者。
    $ p6 p- b3 P! a; C( j' ]
    2 j$ c2 v1 h( A9 _6.1 算术运算
    $ U0 u7 O8 O8 |# G  h8 {gawk 里的算术运算如下所示:
    , m9 S9 j& A6 {) Xx+y 加6 l) L8 V1 m" e( }$ q3 ^' A
    x-y 减8 a4 r. K6 ^; q9 s* e
    -x 负
    # f- T/ y' q7 y( @5 S4 K! u! B" K3 @+x 正。实际上没有任何影响。
    9 J1 Z" ?6 ?& {" px*y 乘9 M- G0 [, _+ f" `7 u+ U$ t
    x/y 除2 D$ X1 K& _: q2 z$ M2 g
    x%y 求馀数。例如 5%3=2。
    ; g$ y, {2 s/ _8 y8 R% E/ }x^y
    # ]+ E- w, e. S, M: D( bx**y x 的 y 次方。例如2^3=8。, y  n9 e1 C) R0 D% r

    9 d4 q! C' p' T3 e6.2 比较算式与布林算式
    , k  g, f& [# x' r1 S, \) W* f比较算式 (comparison expression) 用来比较字串或数字的关系
    3 I5 O4 T2 A2 Y' w! Z1 m, c7 q% X' C,运算符号与 C 语言相同。表列如下:
    & A" ^( z3 C' S' J0 T- Qx<y
    2 O3 `3 I* H; g# \+ {: Px<=y
    ( \( O6 n$ g- y2 K7 q  X. r# Vx>y  I  k- n# `: F( N
    x>=y8 P$ A" j) Y. _& }
    x==y6 b. [# C4 v; U- N- J7 M6 ~
    x!=y# ]( b- |! D6 g+ }; j7 _1 G* I
    x~y, A3 q+ L* e4 k2 S
    x!~y
    4 J# E3 n9 G9 y- C( L: Q0 \( J比较的结果为真(true)则其值是 1。否则其值是 0。) A5 b; g# x) M% Z
    布林算式(boolean expression)有下面三种:
    & U* M6 I& r& S# pboolean1 && boolean2$ \0 C5 N9 k5 i2 h+ r
    boolean1 || boolean2
    7 K# [6 U" X; ~! boolean4 n  m/ O4 }+ S/ I

    . a4 Q, q& l+ g6.3 条件算式(Conditional Expressions)4 P7 D$ ~; R. d/ b- ]+ c
    一个条件式算式是一种特别的算式,它含有3个运算元。
    1 ~1 D" A/ h+ W6 ~条件式算式与C语言的相同:
    0 m0 J4 k  v5 k' h% h- Cselector ? if-true-exp : if-false-exp
    ( ?: e' z# R. a, U1 D它有3个子算式。第一个子算式selector 首先会被计算。如果是真,
    + T8 Q% @0 ?$ l/ H3 s则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-& W6 k) }* d: _8 w- C
    exp 会被计算且它的值变成整个算式的值。: A0 X  G* g% X  T8 D% n( P+ t5 }$ s
    例如下面的例子会产生x的绝对值:  u8 Z  H" N3 x! v- A: N; Z! a- Y
    x>0 ? x : -x
    ) h! g/ N! ]4 H6 d2 t
    ( ]3 G8 @( _! X2 K/ d. O# \2 L) O第七章 Actions里面的控制叙述
    % \0 B, c9 [+ ^/ |在 gawk 程式里面,控制叙述诸如 if、while 等控制程式执行的流
    + U' i; X. l/ r; Z9 g. l程。在 gawk 里的控制叙述与 C 的类似。
    9 p" @# X& i( [8 q很多的控制叙述会包括其它的叙述,被包括的叙述称为 body。假
    ) B! M& {  z0 \' i/ m) P如 body 里面包括一个以上的叙述,必须以大括弧 { } 将这些叙述括起7 l7 f9 Z- y- C' W
    来,而各个叙述之间需以换行(newline)或分号隔开。$ T. }$ y# |. a% r  N# ^
      ]- e, P( `- B) o+ o
    7.1 if 叙述
    9 p" U. Z/ [7 X1 C! mif (condition) then-body [else else-body]! @+ G4 }" \: F- M* o) ^
    如果 condition 为真(true),则执行 then-body,否则执行 else-body。
    & }# ], Y8 e/ q6 Q) |0 L% o, x举一个例子如下:/ [6 A3 _" s* l" V; Q+ B
    if (x % 2 == 0)
    - d) U0 P! N: I! O% kprint "x is even"+ S- G) R8 L/ d% ]' R3 b# q
    else
    % z( h. b; @+ s* y6 Jprint "x is odd"
    . X) I% f* L' J+ l' g2 {& M) b; ?- G2 [4 Q) A  k" {8 \4 ]/ ]
    7.2 while 叙述
      F- }% c5 W% H, v' ~while (condition)6 b, Q4 p' _( p# {8 q& {6 L
    body
    # p6 P( o; ]# y8 k8 uwhile 叙述做的第一件事就是测试 condition。假如 condition 为真则% a; q- d$ M: d  [4 ?7 Z3 l7 x
    执行 body 的叙述。body 的叙述执行完後,会再测试 condition,假如4 _3 i! U) @# H4 }* i
    condition 为真,则 body 会再度被执行。这个过程会一直被重复直到, ^* ~6 s" J9 ~/ w
    condition 不再是真。如果 condition 第一次测试就是伪(false),则
    0 S4 S0 Y: [3 _: c- pbody 从没有被执行。+ m$ g+ H  t* ?& Z# E! z. {
    下面的例子会印出每个输入记录(record)的前三个栏位。
    ( |. u2 ]$ S9 t) z5 F; `gawk '{ i=1
    7 U: r6 @  W! _1 G* Q2 v' _% T# ewhile (i <= 3) {
    7 M2 q- B/ r9 q. l" R) _3 Eprint $i2 h0 h$ ?. V! ~- _! y' Y) N
    i++
    . |' j6 m. p  c9 ~6 C. K}% ^! i: F8 [$ m% X
    }'
    . T, f  @0 [5 A
    % s- \& |% |- q3 Y4 C/ }  o' P) B7.3 do-while 叙述
    ( ^% b# I4 a4 V3 O* udo, d9 a1 F' z8 G. D( L$ g( b
    body6 g) V; g$ S2 C1 |. ]" h( R
    while (condition)
    + F- f+ K* L8 T这个 do loop 执行 body 一次,然後只要 condition 是真则会重复执行 body。
    3 J( b$ o, u* G即使开始时 condition 是伪,body 也会被执行一次。8 W; E6 E! I" r( F" S& v( t3 V0 c
    下面的例子会印出每个输入记录十次。. {- a! w) z/ M) U8 u1 P2 d& Q
    gawk '{ i= 1
    " t; E+ C% N# I% _do {9 l! ?8 f, f9 J! s* y+ P
    print $00 [8 J5 c" K" _5 ~/ g! j
    i++
    0 \; g9 T, F0 E  H} while (i <= 10)
    9 q3 V4 @& G9 B: L# D: B; p+ F}'* n, D# P2 L8 B! a9 e! f8 M

    ; g2 j! c  A$ `, \, _' y7.4 for 叙述3 v, m0 t: x" p* B; B( [
    for (initialization; condition; increment)+ K7 \2 B1 x- s1 D
    body
    % o$ J  Q: [8 v1 c/ C, A7 O. m) I此叙述开始时会执行initialization,然後只要 condition是真,它
    # P# t6 d% T6 R2 Y1 k会重复执行body与做increment 。% V3 U3 g% ]+ R* k7 [
    下面的例子会印出每个输入记录的前三个栏位。
    2 S/ v7 A3 b! v$ J* z; i: S5 ^gawk '{ for (i=1; i<=3; i++)+ ]/ a2 ^2 @& z3 ~4 w+ ~
    print $i- f8 z% y1 |2 V, f" n" ]8 f
    }'# N. b" F( B$ H) {5 z1 z/ d

    4 E: I; }8 n5 }7.5 break 叙述4 G1 q1 R+ G! C1 c2 t: Z
    break 叙述会跳出包含它的 for、while、do-while 回圈的最内层。; _: `" Q6 X) A3 j
    下面的例子会找出任何整数的最小除数,它也会判断是否为质数。
    6 O! R( a  y, ?/ s- ]4 ggawk '# find smallest divisor of num% N$ i: U/ X( v  T( G9 _+ u* j* a
    { num=$11 i% r0 v- Y+ m7 M8 z/ m% f! S
    for (div=2; div*div <=num; div++)+ v5 O6 Y: y% P6 B- _
    if (num % div == 0); a& u5 f. ^2 i7 _: b
    break
    # ^7 o7 k. T8 Cif (num % div == 0)
    6 Q# K" _  q; Y. qprintf "Smallest divisor of %d is %d\n", num, div
    " @/ D5 c* Q6 d3 felse3 n6 l$ Q! s) y, E% A5 k; D4 Y
    printf "%d is prime\n", num }'
    & l; h) V6 o, t5 I. M5 |' b. v9 h3 h
    7.6 continue 叙述
    2 W) v5 t9 \4 x3 r9 Ocontinue 叙述使用於 for、while、do-while 回圈内部,它会跳
    9 e7 [: w5 e* T0 [过回圈 body 的剩馀部分,使得它立刻进行下一次回圈的执行。
    % u+ r3 F' Z3 q' }  @* Y' _下面的例子会印出 0 至 20 的全部数字,但是 5 并不会被印出。
    5 J" B1 Z. x: T7 Hgawk 'BEGIN {
    ) R$ |1 N9 v( T& {# dfor (x=0; x<=20; x++) {
    2 m6 x8 k, \9 m8 g, I8 P1 o% Hif (x==5)5 e% U# [4 d" Z  Z7 k
    continue  S2 P% v/ O6 V! p
    printf ("%d",x)
    5 F7 x7 U9 W8 P. t# Z- Q4 l) }+ d/ m}
    # ]0 l, e2 E0 p% h, }: ]: U; _print ""2 T' B& i9 u- p
    }'3 r% U5 _( i# S  \6 j

    % r9 y, W+ B, W8 p1 P1 N7.7 next 叙述、next file 叙述、exit 叙述
    ' y& U6 R: V  o2 a, j5 s: bnext 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一
    0 j. [$ T; p+ p8 _个记录。
    7 p; d' A% ^# f+ P( X6 d* Gnext file 叙述类似 next。然而,它强迫 gawk 立刻停止处理目前5 H" W  n) s7 H
    的资料档。4 s' ^4 U% q( U+ W, C7 ]
    exit 叙述会使得 gawk 程式停止执行而跳出。然而,如果 END 出现; k% B/ A( V2 a  Z: `$ H) r) n
    ,它会去执行 END 的 actions。) I1 g, b3 \* s; o

    1 L* f' K4 U4 h; c5 _; k第八章 内建函式(Built-in Functions): R( P% b% u: m% a/ S+ s
    内建函式是 gawk 内建的函式,可在 gawk 程式的任何地方呼叫内建! I0 X2 |: P: ?1 a: N
    函式。0 x5 J- ~$ c' J" V
    ( H! s, l1 c1 K+ V  d9 t8 F8 c
    8.1 数值方面的内建函式
    7 k$ B0 ~0 [2 ^/ c) X" r# gint(x) 求出 x 的整数部份,朝向 0 的方向做舍去。例如:int(3.9)
    3 A2 d' Z$ Q, d/ w- [5 B/ S: h3 {是 3,int(-3.9) 是 -3。% K) H0 z! N3 q9 N# v
    sqrt(x) 求出 x 正的平方根值。例 sqrt(4)=2" I4 b+ |. J" K/ g
    exp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。6 n5 V; v6 N2 Z
    log(x) 求出 x 的自然对数。5 H) l$ B5 \; G" M5 C$ E* I
    sin(x) 求出 x 的 sine 值,x 是弪度量。' j6 G# i3 C9 Z
    cos(x) 求出 x 的 cosine 值,x 是弪度量。" I0 K& F/ K+ y3 W7 n, n& F/ }
    atan2(y,x) 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。
    1 O: s8 h1 j- W8 \rand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个( D; j0 I8 @$ F8 U8 `
    值不会是 0,也不会是 1。
    & Q- S. i- v3 a1 o1 }" F8 n每次执行 gawk,rand 开始产生数字从相同点或 seed。" U# B% {8 y6 ]" R) y/ u, m" P5 j
    srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设
    7 B/ ?$ U7 C3 _0 ?定相同的 seed 值,你将再度得到相同序列的乱数值。' F* P, j1 N) e0 i* L: c
    如果省略引数 x,例如 srand(),则现在的日期、时间会5 u, P, p% l( b. q% z
    被当成 seed。这个方法可使得乱数值是真正不可预测的。$ [5 i& T/ H4 J, h
    srand 的传回值(return value)是前次所设定的 seed 值。
    ! h% B% Z8 E& p! ^# @& w- _) l9 @8 ]1 h9 k# p
    8.2 字串方面的内建函式1 T, _  u- C& L  n/ g) W
    index(in, find)9 i0 k' X* O% z$ W% _' X: o" {
    它会在字串 in 里面,寻找字串 find 第一次出现的地方,传回值是' n6 O3 D- f3 L! \$ L0 F7 T
    字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字3 _, S/ H% g  o9 Q6 N# V  e
    串 find,则传回值为 0。
    $ D7 t6 ?4 b" i- W. R) e例如:: ^( L$ t6 ?3 x9 q
    print index("peanut","an")
    4 T' H2 l& D7 B" n会印出 3。
    ; n8 \+ B  l* |- I' T9 k- R& flength(string)
    7 x# y! X8 k7 T" r9 v. o求出 string 有几个字元。
    # b; b% }' w  B, _2 Q例如:
    9 J4 M% f0 K9 Vlength("abcde")
    : I! r' h' A! F( k是 5。
    6 c% m: k2 x- I+ k3 d& {5 Umatch(string,regexp)3 }5 t& }5 x1 l5 r
    match 函式会在字串 string 里面,寻找符合 regexp 的最长、最靠. k( d: B+ @# @3 E4 i
    左边的子字串。传回值是 regexp 在 string 的开始位置,即 index
    1 ]* u1 z" Z( o) `( x; b值。5 I7 W: y0 w) t' N# ^2 c
    match 函式会设定内在变数 RSTART 等於 index,它也会设定内在变
    4 g- k7 o3 U, s+ z数 RLENGTH 等於符合的字元个数。如果不符合,则会设定 RSTART 为
    ) `; ]8 X' G6 {) a0、RLENGTH 为 -1。
    + M, s$ [& M& p7 Zsprintf(format,expression1,...)
    / x# F& V( a7 d8 V+ H$ ^7 c举 printf 类似,但是 sprintf 并不印出,而是传回字串。4 E/ W, v4 H- T) J# g
    例如:
    8 p4 W7 ^/ P- ~: u3 L* Ysprintf("pi = %.2f (approx.)',22/7)8 r8 f1 j! P8 v8 A4 e, }
    传回的字串为"pi = 3.14 (approx.)"+ l: `# V/ L+ i
    sub(regexp, replacement,target)
    7 z4 z6 O9 f/ ?& Z  h7 q3 E7 z, h% X在字串 target 里面,寻找符合 regexp 的最长、最靠左边的地方,
    6 T% Z% v# E' {3 `$ ^1 W" n以字串 replacement 代替最左边的 regexp。& l' i, T3 G0 C/ W7 `
    例如:
    4 W; ]# X: i0 Qstr = "water, water, everywhere"
    # Q8 y) x  h) Y' x* p% \2 dsub(/at/, "ith",str)8 @1 ]% {% E/ u; n
    结果字串str会变成( T  R* N; f  p7 b4 M! T+ P
    "wither, water, everywhere"3 d4 E3 n  R: {( Q. o
    gsub(regexp, replacement, target)  W- T) P/ R1 p/ X; D  e
    gsub 与前面的 sub 类似。在字串 target 里面,寻找符合 regexp 的2 r% b% j$ A. O  d1 g2 x) G$ x4 k
    所有地方,以字串 replacement 代替所有的 regexp。
    1 O8 V/ Q" B) N8 o) G2 z例如:2 x) H5 M' M0 H
    str="water, water, everywhere"7 K  a- X$ ]. ^! u8 g- j
    gsub(/at/, "ith",str)
    " b  V2 o" T* G1 \结果字串str会变成
    # Z/ }9 }# A8 G& I% W/ O'wither, wither, everywhere"8 ?2 b& R! b) k/ l, A  |0 ^- r  j" _) l
    substr(string, start, length)
    5 O  |+ Z" j! ?7 Q传回字串 string 的子字串,这个子字串的长度为 length 个字元,
    ! p, Z  ^( d( ~# M2 p. P( r从第 start 个位置开始。
    3 s  n' h  y( V% f' X例如:
    7 W3 y$ O& p. A; |5 i) C4 h( @substr("washington",5,3)
    ) p& q# ~. E4 r1 j: Q传回值为"ing"
      I  X: D' j1 ^' g( p2 |如果 length 没有出现,则传回的子字串是从第 start 个位置开始
    ( Y7 O% O* \! _( j至结束。
    0 Y' j0 T! P4 e& c7 }8 P7 h例如:5 c5 T# i$ j* z" a6 O
    substr("washington",5): [/ ]$ h9 K" H: ~
    传回值为"ington"
    ' ?* L. e$ X* P: m! V* C1 ?' N; rtolower(string)
    ' E$ Z' K8 q/ s! ]& i/ f将字串string的大写字母改为小写字母。7 a1 N# K3 ]. L& Z) A2 v/ p
    例如:9 `9 y' O5 P) @5 [% o
    tolower("MiXeD cAsE 123")* \  n; `  y+ m0 U1 A: W, O& I
    传回值为"mixed case 123"
    - k* {5 }! A/ Z: W$ a* |+ Stoupper(string)! C7 ]- I  z1 ]# V3 |
    将字串string的小写字母改为大写字母。6 I$ w9 V9 l/ y9 b. _- r
    例如:$ s( }3 C9 d9 ?& t3 |
    toupper("MiXeD cAsE 123")
    5 T" e  I4 |. y  o% l* W( ~0 ~) Q7 D传回值为"MIXED CASE 123"
    5 e! g: q2 E* u( e& }8 R# z  O6 u$ ]3 f, M8 H. L% W9 M
    8.3 输入输出的内建函式
    4 [! h( y9 r7 i. Q  }close(filename)
    : b6 \: d" e# ?将输入或输出的档案 filename 关闭。" b, z" ~# x* n4 E
    system(command)2 E1 a6 c3 _: Y2 m( ~9 N8 h: [( R5 u
    此函式允许使用者执行作业系统的指令,执行完毕後将回到 gawk
    ) o+ ^+ c! U6 y( R) u. w程式。, b% d* ~9 x3 _) s4 G
    例如:
    8 }# n0 |! L/ y* u; f  |BEGIN {system("ls")}
    ) u2 V6 J/ l8 a
    8 [, f) u: b: K  W第九章 使用者定义的函式(User-defined Functions)
    & J  b" ^' ]2 b8 s, h: E6 s复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用( H# @3 d+ x: e
    者定义的函式与呼叫内建函式的方法一样。; K2 u* e" H( a. Z

    ) m3 u- ~7 x% M; Y! ^$ a: P9.1 函式定义的格式
    ! }6 \) |. z; N3 R函式的定义可以放在 gawk 程式的任何地方。
    / S1 K) ?: P- w$ t3 Q( ]$ A一个使用者定义的函式其格式如下:+ s4 d4 B; w8 B" C3 y
    function name (parameter-list) {6 `3 T* O$ ^3 T8 i% k8 a
    body-of-function
    + K. W. W: T- N( p& E  O3 b}7 V. G1 c& B% U! T3 T# S
    name 是所定义的函式之名称。一个正确的函式名称可包括一序列的字
    + v* t, S8 ?7 I3 R! m* k母、数字、下标线 (underscores),但是不可用数字做开头。. g: p. O+ B! K4 l! U( N
    parameter-list 是列出函式的全部引数(argument),各个引数之& x9 V2 d' I8 X( ~  N# h$ F
    间以逗点隔开。
    ; Q+ _$ ~! B6 Z  s( Q0 pbody-of-function 包含 gawk 的叙述 (statement)。它是函式定义
    ! K4 B9 [( i+ ~# y& t里最重要的部份,它决定函式实际要做何种事。
    ' O; x* t' f' \; n" t' e8 n* Y" ~$ [% {- y+ D! K2 f  T( S
    9.2 函式定义的例子
    # t+ t' p0 k% ]& ~7 Z# }" u% |5 f下面这个例子,会将每个记录的第一个栏位之值的平方与第二个
    ! e) T5 e2 n! g" L3 x* \栏位之值的平方加起来。1 H2 @0 S: a6 d# f$ V
    {print "sum =",SquareSum($1,$2)}% J  I' o+ i7 E4 @. W4 C. m" _
    function SquareSum(x,y) {' }6 R- A+ Z$ P9 \6 [8 W' t
    sum=x*x+y*y
    . z' z5 }$ ~& R; E2 u* e. q* ureturn sum
    $ ^- ?" C% _+ P; m3 `8 g" C}' h5 p8 q) E* r+ {# c
    ) Y1 o4 L' J0 R: m. }
    第十章 □例/ j% N, f+ z, F8 A  D
    这里将列出 gawk 程式的一些例子。6 A$ Q+ K9 m6 J% ~& ?" A/ b
    gawk '{if (NF > max) max = NF}
    * M. p% u1 t8 Q+ m! @END {print max}'
    * E9 U2 F( a0 W/ u此程式会印出所有输入行之中,栏位的最大个数。6 T$ ~, Q* W6 [' M4 U" P! ^, \4 V% a5 b+ F
    gawk 'length($0) > 80'. f6 F8 Q5 n2 j$ y
    此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被. S4 M$ t7 c0 l" W( r
    列出,action 是采用内定的 print。
    5 G7 ]' L8 s6 C$ G, [gawk 'NF > 0'
    5 ^* m( g( U. R* e: S5 p5 ]对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简
    ) y+ K/ R% |1 ^0 r7 c单的方法,将一个档案里的所有空白行删除。
    ! h/ {  h) a1 K" i/ Lgawk '{if (NF > 0) print}'* G4 z! ^' P8 ?2 h% Z( g* m1 L' `
    对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简4 S7 J+ m- Q: R3 }$ ^: Q
    单的方法,将一个档案里的所有空白行删除。
    6 v! Q; @" ?" S0 Xgawk 'BEGIN {for (i = 1; i <= 7; i++)/ w+ p7 {$ a% q6 y4 o6 U( R
    print int(101 * rand())}'2 g8 e% B0 O' G1 K( P3 ]
    此程式会印出□围是 0 到 100 之间的 7 个乱数值。/ b6 ~) F3 ^& I% {
    ls -l files | gawk '{x += $4}; END {print "total bytes: " x}'# F0 y0 c  C3 u0 t% a& L$ s/ c
    此程式会印出所有指定的档案之bytes数目的总和。, K6 a7 F/ M6 Q7 a$ x5 Z
    expand file | gawk '{if (x < length()) x = length()}7 b" V7 G0 i6 s3 l- K$ q
    END {print "maximum line length is " x}'
    7 b: F  m/ [; P2 j3 V5 @8 I此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改  j" J5 E/ k6 G9 b6 \9 M
    成 space,所以是用实际的右边界来做长度的比较。
    5 _" v1 ^5 C$ k; P5 N6 x; k! C) ?gawk 'BEGIN {FS = ":"}
      R* P5 e/ y, r- M; P{print $1 | "sort"}' /etc/passwd" q* K6 I- {$ y; a" ^
    此程式会将所有使用者的login名称,依照字母的顺序印出。2 K1 J; B3 A8 i# d
    gawk '{nlines++}
    4 N: H5 ~+ B4 C  T4 V; Y- C, uEND {print nlines}'
    / o7 B8 K4 m* d8 B- u此程式会将一个档案的总行数印出。! u* t1 z, s- o0 Z; N
    gawk 'END {print NR}'
    * n& h# B# f3 f5 d/ {, E此程式也会将一个档案的总行数印出,但是计算行数的工作由gawk
    & y0 v) K$ e- `: S来做。7 v$ [( H: k% C+ F, }! \
    gawk '{print NR,$0}'
    1 o9 t% U; O& E+ b$ O. j此程式印出档案的内容时,会在每行的最前面印出行号,它的功
    8 R* ~2 _/ {8 h# s5 ^能与 'cat -n' 类似。( M6 \8 D! i* g- Z" V* h# i

    0 Q2 }/ F$ O8 ], [第十一章 结论
    : N5 l8 J5 v0 m9 N* q/ Vgawk 对於资料的处理具有很强的功能。它能够以很短的程式完成' r/ m" I2 k; H) V
    想要做的事,甚至一或二行的程式就能完成指定的工作。同样的一件
    . E9 |+ r) J8 k! \( [- |6 U工作,以 gawk 程式来写会比用其它程式语言来写短很多。& [* W' _6 G  H: p$ O
    gawk 是 GNU 所做的 awk,它是公众软体(Public Domain) 可免费使, F0 M5 a) |1 _- F( @/ v
    用。
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    楼主热帖

    相关帖子

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

    该用户从未签到

    尚未签到

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

    本版积分规则

    招聘斑竹

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

    GMT+8, 2025-2-23 19:54

    Powered by Discuz! X3.5 Licensed

    © 2001-2025 Discuz! Team.

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