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

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

Gawk手册

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

    连续签到: 1 天

    [LV.1]初来乍到

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

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

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

    ×
    GAWK5 ]2 {9 u, r4 z: W/ M
    第一章 前言
    ! a) `& l: |% B1 ]0 v0 s第二章 简介! H: a! z/ x4 m6 a3 ~/ M
    第三章 读取输入档案
    4 V$ U  o- m, r% }第四章 印出
    ; J* y6 q- U9 M. E8 [9 s1 N$ ^第五章 Patterns1 q+ X' z! }6 z/ Y5 [$ ^1 Z. Z+ k
    第六章 算式(Expression)作为Actions的叙述
    ! E! u1 e1 {# |0 U第七章 Actions里面的控制叙述2 V8 I& t$ O; e. {3 ], ^- r
    第八章 内建函式(Built-in Functions)
    7 f; s) U! E3 |4 e7 `4 W& b第九章 使用者定义的函式6 w' U( ?6 B. Z; u+ M- G1 @& F- Y
    第十章 □例
    5 g6 i6 a0 k. D5 ^1 J第十一章 结论6 e3 V: P8 k' R! p7 D' Y

    6 m  s5 F' r/ Y0 [6 H* f) L=======================================
    $ L/ q9 T7 {0 K: M8 @第一章 前言
    ( C& T9 Y, p( Jawk 是一个程式语言,对於资料的处理具有很强的功能。对於文, v) h/ L: W! V# O
    字档里的资料做修改、比对、抽取等的处理,awk 能够以很短的程式+ ?% L; k& p! ^/ ^# V4 ~
    轻易地完成。如果使用 C 或 Pascal 等语言写程式完成上述的动作,
    " Y6 Z' @9 F2 A& V. L2 F5 D会不方便且很花费时间,所写的程式也会很大。) e8 I! p2 W9 F! N  T
    awk 能够依照使用者的定义格式来分解输入资料,也可依照使用5 m9 u& Q0 X4 w: Z, H! N
    者定义的格式来印出资料。
    : U2 y, q. I+ uawk 名称的由来是由它的原始设计者的姓氏之第一个字母而命名# C" ?2 E6 |# f
    :Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。' P+ L2 m; I/ O5 w" l
    awk最初在1977年完成。一个新版本的awk在1985年被发表,它的功能: ^" t. P1 x. h$ `! _# Y( z: p
    比旧版本增强不少。& M$ G7 ]5 e$ a! M- a5 |! V
    gawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不断地
    0 Z3 s/ ~: S* h2 F. A5 H. C被改进、更新。gawk 包含 awk 的所有功能。( @; X$ n+ }& _5 B
    往後的 gawk 将以下面的2个输入档案来做例子说明。* g5 C: z4 \4 Q8 v! ^
    档案'BBS-list':
    * ]6 W, t0 t& @9 s# |( Eaardvark 555-5553 1200/300 B
    2 p+ q/ M9 K9 M9 Q7 M4 B, Nalpo-net 555-3412 2400/1200/300 A1 A0 ?4 T( l, U3 H6 \
    barfly 555-7685 1200/300 A# A1 Z* X  ?3 \/ Z4 g! n! h5 q9 g  o( I
    bites 555-1675 2400/1200/300 A
    , D9 [+ B5 J5 [& E* b, Zcamelot 555-0542 300 C
    ; Q1 j7 [3 m: y5 `1 ?* ^5 }core 555-2912 1200/300 C, u6 B8 R: i5 W; v: r; Q3 j* g$ {
    fooey 555-1234 2400/1200/300 B
    $ |0 ~' }: g+ b1 S+ D8 Afoot 555-6699 1200/300 B. L8 `9 i* @' ^
    macfoo 555-6480 1200/300 A# z" \) v& e# M; S! v. s
    sdace 555-3430 2400/1200/300 A
    $ c& k! M7 \$ d( T; @# ysabafoo 555-2127 1200/300 C
    ' `9 ~$ ]& D/ @9 w& {( z$ ~档案'shipped':2 w* g+ }6 t% R0 O1 f% d0 x
    Jan 13 25 15 115
    8 Y" ^8 M8 a2 |1 I0 r2 U2 f1 aFeb 15 32 24 226
      d- U( i+ U2 v; ^( ]1 s4 L5 _* ?% ?Mar 15 24 34 228
    + H  a5 h7 z+ _' f' aApr 31 52 63 4208 S6 I' d: ~7 ~# m; E2 [
    May 16 34 29 208& q) r- y8 l5 ?5 q* m9 r0 b& v: R
    Jun 31 42 75 492
      ^/ u5 r5 f2 K" _; k3 v) [Jul 24 34 67 4362 U# b# I+ w, y
    Aug 15 34 47 316
    $ O. x; e5 w' S9 TSep 13 55 37 277
      m; A2 l& p; ?/ h  Q0 YOct 29 54 68 525* d1 i- e* |9 Y
    Nov 20 87 82 5776 [# t- ^* Z% b$ {- [* f- L
    Dec 17 35 61 401
    7 `' {+ M' e6 i* Z7 h6 c6 K9 kJan 21 36 64 620, J& ^6 ]# {1 R6 H
    Feb 26 58 80 652
    , t2 q# v. r: G, SMar 24 75 70 4954 O& T8 D# c  k1 N
    Apr 21 70 74 514! {+ w; T, L. a8 b6 x+ G

    & c3 |' k; K' g& V第二章 简介% g, H  Q) [/ q# f. H' k9 |
    gawk 的主要功能是针对档案的每一行(line)搜寻指定的 patterns
    $ z, d2 X! X3 W2 |$ ]  m# l6 Q' G; G。当一行里有符合指定的 patterns,gawk 就会在此一行执行被指定0 G3 p) r$ P$ O
    的 actions。 gawk 依此方式处理输入档案的每一行直到输入档案结
    7 P, F$ Y! Q/ h- Q) `3 F) u, @束。3 X4 @7 [# u0 x+ j& u8 y$ c
    gawk 程式是由很多的 pattern 与 action 所组成,action 写在* [3 n  a0 J( a# B8 S
    大括号 { } 里面,一个pattern後面就跟著一个action。整个 gawk 程
    3 |& S6 i8 e8 F* G( a" x, v- L6 v式会像下面的样子:8 j( U8 L- S/ }% }" {9 v* k: [
    pattern {action}% \- c+ B+ s" N; d4 Q  c
    pattern {action}  |4 I/ W6 f5 X. v9 q1 I1 y
    在 gawk 程式里面的规则,pattern 或 action 能够被省略,但
    , Q; @# Q$ P" e是两个不能同时被省略。如果 pattern 被省略,对於输入档里面的% t# W+ L( D. t( A/ H
    每一行,action 都会被执行。如果 action 被省略,内定的 action+ N/ O( A9 \4 m, v! x
    则会印出所有符合 pattern 的输入行。; h, x1 K+ q- |+ F, l4 u" ?8 M1 M

    3 S9 n2 O) U  D3 Q/ t( {2.1 如何执行gawk程式
    3 C& ~7 S1 c% f基本上,有2个方法可以执行gawk程式。
    $ X. `0 ]! Q' Z4 T. J; h□如果 gawk 程式很短,则 gawk 可以直接写在 command line,如下所示:
    : K. R5 K; x" sgawk 'program' input-file1 input-file2 ...5 S& E7 E4 Y! h) O) l
    其中 program 包括一些 pattern 和 action。& M; x# H: v1 [3 k
    □如果 gawk 程式较长,较为方便的做法是将 gawk 程式存在一个档案,
    4 r5 \% y" H, `2 S6 s+ u; F+ ^即 patterns 与 actions 写在档名为 program-file 的档案里面,执行
    7 i$ o, u6 U* pgawk 的格式如下所示:9 L: q6 x% l1 u) k  x1 c! Q
    gawk -f program-file input-file1 input-file2 ...* Y  v! g, B7 T& Z$ t
    gawk 程式的档案不止一个时,执行gawk 的格式如下所示:' W. z" e7 O- i2 |
    gawk -f program-file1 -f program-file2 ... input-file1
    , E$ I$ N$ D; ?% @! Pinput-file2 ...6 A4 j5 v% ^1 l* k7 D6 r2 s4 S
    % Z0 Q3 ]% k4 e7 I8 j
    2.2 一个简单的例子. O1 x$ o: a/ ^6 s# N" r. ?
    现在我们举一个简单的例子,因为 gawk 程式很短,所以将 gawk 程5 q* o1 Q/ y! B1 Z, ]! @
    式直接写在 command line。3 e9 ~6 N6 O$ u$ c5 A/ d
    gawk '/foo/ {print $0}' BBS-list. j# i( W3 l2 o
    实际的 gawk 程式为 /foo/ {print $0}。/foo/ 为 pattern,意思为搜4 j2 G0 K0 X/ \9 X$ M$ J: z
    寻输入档里的每一行是否含有子字串 'foo',如果含有 'foo' 则执行 action。
    ' ]3 u  s# F  P! ?4 ~7 ^7 [& f, `action 为 print $0,是将现在这一行的内容印出。BBS-list 是输入的档案。1 c0 j6 d. h, l7 D! V/ m
    执行完上述指令後,会印出下面的结果:. c  L0 F8 O$ U/ [3 l
    fooey 555-1234 2400/1200/300 B) r# M- A  T" e) |) q5 H3 d
    foot 555-6699 1200/300 B
    / `# [$ K$ q; a: e+ amacfoo 555-6480 1200/300 A
    3 H7 D6 c1 {4 p+ Isabafoo 555-2127 1200/300 C* t" o- I7 H. P8 S7 ~* i

    * @) f+ \) L. |) L2.3 一个较复杂的例子
    6 w: a2 g( A7 J1 D3 agawk '$1 == "Feb" {sum=$2+$3} END {print sum}' shipped+ r2 w! a6 c- V4 p
    现在这个例子会将输入档 'shipped' 的第一个栏位与 "Feb" 做比较/ u9 {1 Q# h3 o  F& ]5 D/ d+ k
    ,如果相等,则其对应的第2栏位与第3栏位的值会被加到变数 sum。
    4 x$ V& x3 h# I) }1 b4 b# d对於输入档的每一行重复上述的动作,直到输入档的每一行都被处理: ~  W% S+ v" B/ D
    过为止。最後将 sum 的值印出。END {print sum} 的意思为在所有的输1 n, {5 \$ x, q
    入读完之後,执行一次 print sum 的动作,也就是把 sum 的值印出。$ s8 S" t6 `% |
    下面是执行的结果:
    6 ]' ]3 B- n( p& z# B- s  x84
    ; Z/ v6 I  B; q3 e+ D. {5 y0 q6 s+ Z0 r
    9 x, X- O) Y! N# j4 M# ~& [6 m第三章 读取输入档案* M" |8 ~/ B3 I4 ?1 F
    gawk的输入可以从标准输入或指定的档案里读取。输入的读取单
    . E7 r; J+ g9 U% V$ [% _1 D位被称为”记录”(records),gawk 在做处理时,是一个记录一个记
    5 D) q: a+ V! \6 q- f+ {0 F0 j录地处理。每个记录的内定值是一行(line),一个记录又被分为多个
    # H9 X; P% ?6 O# s栏位(fields)。' C5 T4 `1 S2 m  p
    7 x* R4 t# y# y6 T( \5 _3 D
    3.1 如何将输入分解成记录(records)% ~1 O4 I% @9 H7 u6 w; Q- X) S
    gawk 语言会把输入分解成记录(record)。记录与记录之间是以) x# }' {- b6 x  s! d+ c, L
    record separator 隔开,record separator 的内定值是表示新一行的
    # {' K6 Z7 ^" ~" P0 x1 |1 G字元(newline character),因此内定的 record separator 使得文字
    " p. {2 W. v, {" Q1 t& O9 I的每一行是一个记录。1 {- C4 x/ a1 _+ s  Q% K
    record separator 随著内建变数 RS 的改变而改变。RS 是一个字串,
    , u4 h. |9 k3 T) s# O$ b; w/ \它的内定值是"\n"。仅有 RS 的第一个字元是有效的,它被当作 record; `. g- W7 s# {. U$ h
    separator,而 RS 的其它字元会被忽略。
      d- _0 u! c- L内建变数 FNR 会储存目前的输入档案已经被读取的记录之个数。内
    6 S& f$ V, K$ v5 g0 G建变数 NR 会储存目前为止所有的输入档案已经被读取的记录之个数。
    2 r& L6 m" e! L% T! Z
    , ]: X) T, t8 y2 N) D3.2 栏位(field)
    4 |5 P' U1 O$ [( H% C. Rgawk 会自动将每个记录分解成多个栏位 (field)。类似於字在一4 U# J9 O( u8 [3 a' J8 D, X, D
    行里面,gawk 的内定动作会认为栏位之间是以 whitespace 分开。在
    6 g7 A; e, I: I4 J' kgawk 里,whitespace 的意思是一个或多个空白或 tabs。
    : B( l' q) \  V在 gawk 程式里面,以'$1'表示第一个栏位,'$2'表示第二个栏位# V8 B* y! z  ]
    ,依此类推。举个例子,假设输入的一行如下所示:
    ) J' J9 F2 ^$ @9 |This seems like a pretty nice example.
    1 o% G& y) y4 C1 V" {9 w第一个栏位或 $1 是'This',第二个栏位或 $2 是 'seems',依此类推。4 E3 J9 W) _6 b% g, _$ F
    有个地方值得特别注意,第七个栏位或 $7 是'example.'而非'example'。
    & u( Y3 }8 Z+ y- v7 {% e不论有多少栏位,$NF 可用来表示一个记录的最後一个栏位。以% ^  K+ k+ z0 i- R4 L# Q8 j
    上面的例子为例,$NF 与 $7 相同,也就是'example.'。
    & Z$ }9 ?* p9 t$ |- o3 ~NF 是一个内建变数,它的值表示目前这个记录之栏位的个数。4 k% ~+ _5 x3 L: z+ @
    $0,看起来好像是第零个栏位,它是一个特例,它表示整个记录。: |- a% K1 B% {0 S( W( t
    下面是一个较复杂的例子:. _" R: L, M/ U
    gawk '$1~/foo/ {print $0}' BBS-list& X: h4 g2 g2 Z+ V
    结果如下:* {* C3 Z& Y3 x: z! ~
    fooey 555-1234 2400/1200/300 B
    . e! ~; o4 M1 {  wfoot 555-6699 1200/300 B
    * C5 H& _; |. I/ V  o' Zmacfoo 555-6480 1200/300 A' C$ `( |  q* p
    sabafoo 555-2127 1200/300 C
    6 g# m3 t& M! F- K% d这个例子是把输入档'BBS-list'的每个记录的第一个栏位作检查,如2 M3 E! R; K  T0 m& |$ n
    果它含有子字串'foo',则这一个记录会被印出。% U8 i# F  i: F- U$ W. Y

    3 ?+ N! ~' m' j  R- a3.3 如何将记录分解成栏位0 L1 J3 l& \+ S/ v2 a
    gawk 根据 field separator 将一个记录分解成栏位。field sepa-( r+ A4 Y6 R8 c9 b' i  ^! J; z
    rator 以内建变数 FS 表示。9 \& B' m3 r& X/ m; T
    举个例子,假如 field separator 是'oo',则下面的行:
    ) b" E& G( d7 ]+ w3 C5 v$ nmoo goo gai pan1 O/ \) S8 n( ^. M  S- j( e
    会被分成三个栏位:'m'、' g'、' gai pan'。! G6 c8 w* ?+ s9 Z5 f
    在 gawk 程式里,可以使用'='来改变 FS 的值。例如:( r' R+ U8 W/ F* `6 @* g
    gawk 'BEGIN {FS=","}; {print $2}'' F9 f- G! L: q, Z" j
    输入行如下:6 i) r3 y0 }& E4 [; \4 Y
    John Q. Smith, 29 Oak St., Walamazoo, MI 42139
    8 W; s- I: m: D$ x- j执行gawk的结果将印出字串 ' 29 Oak St.'。BEGIN 後面的 action 会在; u8 U* k1 r( |1 m$ B. D" a7 r3 D' @
    第一个记录被读取之前执行一次。+ W: _$ {* r/ t$ A1 T
    ' w, H" h6 P7 W$ c) x3 Z: ~
    第四章 印出$ l- Y. H) k0 I: z
    在gawk程式里,actions 最常做的事就是印出(printing)。简单6 {7 M. \: D- R6 M! K! p
    的印出,使用 printe叙述。复杂格式的印出,使用 printf 叙述。
    2 M% o/ g! v2 c  n
    2 p9 G+ n" k5 d. n& \4.1 print叙述
    * C- R! L. c0 B2 ]2 n7 m$ \print 叙述用在简单、标准的输出格式。叙述的格式如下所示:- l( }$ E$ d, I" O( f% P
    print item1, item2, ...
    0 Y! N5 r: h$ f+ I- U# V7 J  t1 U输出时,各个 item 之间会以一个空白分开,最後会换行(newline)。, c# R; p$ ^& c. Z/ m
    如果 'print'叙述之後没有跟著任何东西,它与'print $0'的效
    1 {9 z3 T. J  E6 E& z- V/ u0 E果一样,它会印出现在的记录(record)。要印出空白行可使用'print! X% F$ c! p' p- X" B: W3 K
    ""'。 印出一段固定的文字,可用双引号将文字的两边括起来,例如4 ^' v8 Q; I3 b( |8 C( c
    'print "Hello there"'。: R9 Z0 f/ m$ e) y4 K
    这里是一个例子,它会把每个输入记录的前二个栏位印出:, B3 m3 i' o2 y! Z
    gawk '{print $1,$2}' shipped
    / j* C2 Z1 P0 Y3 q+ |& s& b  r' z结果如下所示:
    9 c* K  o( A% h1 L; GJan 13
    7 ?2 K; R3 V8 f0 x) qFeb 15
    9 |. ~4 A$ q8 n! NMar 15
    2 ~& o" ^7 ~8 R3 t+ ^  y5 YApr 317 i& i: C1 F0 q( @
    May 16) y* N1 N, {! ?3 Z! b0 U
    Jun 31# j. h2 A" A/ o  ~  Y2 b& f
    Jul 24
    ) V# ?( J3 V$ P2 T( MAug 15. [' l6 z' y- s6 Q) h/ a$ [
    Sep 13! J) O# [+ j0 t7 C/ S5 k/ m
    Oct 29
    / Y1 ]8 ~1 O, ^; iNov 20
    ( W+ D7 g. X  v) O" jDec 17
    & O; Y$ G( r& j( j# U% BJan 21
    + w: T" ^! `9 ]Feb 266 e2 l$ C7 b: I
    Mar 24' N( r7 f2 @( ]+ q6 f: }
    Apr 21; W" C8 A% U  L& Y- K" n% j
    * ]+ x1 {# @7 h& X  ^
    4.2 Output Separators: Y8 Y- s( I, u; ~1 a
    前面我们已提过如果 print 叙述包含有多个 item,item 之间1 }5 f/ r* H2 w; E
    用逗点分开,则印出时各个item会被一个空白隔开。你能够使用任何
    : p4 L# ]1 L" z: E& h的字串作为 output field separator,可以经由内建变数 OFS 的设
    $ K6 a9 ^2 E2 {: a# H; l; d定来更改 output field separator。OFS 的初始值为" ",即一格的
    , e4 n( H2 H+ W! \空白。
    5 @5 {: c  E) `  \' A整个 print 叙述的输出被称为 output record。print 叙述输
    * V2 B  ]8 G# O: j8 D出 output record 之後,会接著输出一个字串,此字串称为 output% u% Z, a& d% N. q) p
    record separator。内建变数 ORS 用来指明此字串。ORS 的初始值
    ) _! C1 H# N! w: q" x为 "\n",也就是换行。  J% A+ }* O" F1 q5 }0 \) c
    下面这个例子会印出每个记录的第一个栏位和第二个栏位,此二
    6 D, E, o; J# w" a个栏位之间以分号';'分开,每行输出之後会加入一个空白行。- f! [; o+ ?. D* Q+ z3 N/ H- p2 E& S
    gawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list% u  ~9 |9 x4 v" A9 o# K" p. Y% ?
    结果如下所示:. v$ [  b" k. c# ^$ H
    aardvark;555-55532 V+ b: ]9 C4 D% J0 C% l
    alpo-net;555-3412
    + T9 P. [. k" L& C( x* Q% Q# ^barfly;555-7685
    . i( C* @& t. Vbites;555-1675
    % r6 e0 P: ?4 k  Zcamelot;555-0542
    # k6 t4 P4 e& u2 x$ @" ]6 mcore;555-2912) R( n1 m; ~8 s1 B# W) N
    fooey;555-1234
    2 \% A6 z3 X3 y2 d9 r( e- f) hfoot;555-6699
    + s' f: l9 |5 {* o" ~0 Y* tmacfoo;555-6480
    % R7 g$ ~2 j; e0 b' {  b0 Bsdace;555-34309 K$ `# a6 t5 i  c6 D( w3 d" V
    sabafoo;555-2127
    2 X/ T1 G% @$ U% ?+ v! ]8 @, Z% ^9 X1 N5 i0 e* @$ D
    4.3 printf叙述. Q) D. F9 O+ k+ @0 s, i) P' v
    printf 叙述会使得输出格式较容易精确地控制。printf 叙述可以
    4 Y6 ~/ ^& I- }0 r( G7 \1 p, }1 x指定每个 item 印出的宽度,也可以指定数字的各种型式。
    0 f# }* J6 c6 a, W, |printf 叙述的格式如下:
    ' @1 C. ]3 l3 n3 nprintf format, item1, item2, ...
    , a! Z0 H/ I* V: D) Y" Xprint 与 printf 的差别是在於 format, printf 的引数比 print* }' a+ j' D% n6 S
    多了字串 format。format 的型式与 ANSI C 的 printf 之格式相同。' }. P3 j) |& t0 K
    printf 并不会做自动换行的动作。内建变数 OFS 与 ORS 对 printf 叙* ]$ q- W8 w8 F
    述没有任何影响。6 Y* w9 S$ u" t% N2 W/ o9 G6 _
    格式的指定以字元'%'开始,後面接著格式控制字母。/ p% Y0 K2 b9 j
    格式控制字母如下所示:# p! Z4 @9 _1 u: ?9 s0 T( m
    'c' 将数字以 ASCII 字元印出。+ |, n2 b5 P. e, L- o
    例如'printf "%C",65'会印出字元'A'。4 t. a4 A1 p- ~+ x8 n- w, o
    'd' 印出十进位的整数。, N7 d* F! r7 A3 V% H1 R# B4 t
    'i' 印出十进位的整数。6 H/ z; |0 E$ K, Y) K+ M4 H  i
    'e' 将数字以科学符号的形式印出。
    3 {: m8 ]# l' C例如; h2 i& g/ [6 Z
    print "$4.3e",1950
    - q2 l! v7 O( S9 y, |. Y! d( R3 f结果会印出'1.950e+03'。( ~: C# @+ |3 @
    'f' 将数字以浮点的形式印出。/ ]8 l) m1 w2 X4 f
    'g' 将数字以科学符号的形式或浮点的形式印出。数字的绝对值如果9 v- h! \6 f1 R4 P
    大於等於0.0001则以浮点的形式印出,否则以科学符号的形式印4 W! R' V+ r6 w% M
    出。
    4 q6 D6 [8 ~% ~1 ]8 h'o' 印出无号的八进位整数。
    , C" d2 e, ?/ b* g0 X6 C' @'s' 印出一个字串。
    . m) ^! N6 F: H# e& m'x' 印出无号的十六进位整数。10至15以'a'至'f'表示。2 k) x* ~" r. W3 T9 c2 X
    'X' 印出无号的十六进位整数。10至15以'A'至'F"表示。
    # [6 p/ M! s. |# Q& x  c'%' 它并不是真正的格式控制字母,'%%"将印出"%'。! z* p3 K4 C/ ~$ e: p1 \' {
    在 % 与格式控制字母之间可加入 modifier,modifier 是用来进一/ Y5 Q2 E$ f9 U) a3 P, T  y8 }
    步控制输出的格式。可能的 modifier 如下所示:: ~- D$ \# x0 R8 K  \# Z& d/ p, Z
    '-' 使用在 width 之前,指明是向左靠齐。如果'-'没有出现,则会在( G' ^, K- s. `8 G6 H; u3 w
    被指定的宽度向右靠齐。例如:
    ( [+ _; D2 G0 E; S& V2 f' _printf "%-4S", "foo"
    : P; Q" g# v/ H3 |; |0 T1 t) N0 l会印出'foo '。
    ; Q  g% o, G2 g- g7 S'width' 这一个数字指示相对应的栏位印出时的宽度。例如:7 y0 T0 ]* R: q0 F
    printf "%4s","foo"
    * R" Y' d1 j: j7 C; I会印出' foo'。, o1 Y7 |# b) {+ X
    width 的值是一个最小宽度而非最大宽度。如果一个 item 的
    $ q) r- Q% v6 D& M/ Q9 f值需要的宽度比 width 大,则不受 width 的影响。例如4 T  Z+ ~* n: s( D. |$ B3 R
    printf "%4s","foobar"  H6 d! g1 z. Y0 j
    将印出'foobar'。2 a4 s( G/ q' J  ]5 a
    '.prec' 此数字指定印出时的精确度。它指定小数点右边的位数。如
    ) Q) c) J* H$ d& o4 X果是要印出一个字串,它指定此字串最多会被印出多少个字! i0 g3 [; v+ O4 ]% `6 b
    元。6 Z1 K1 O# b6 A* |; a
    3 |. d, e. m( g. _+ M$ Z& Y# S! ]- d
    第五章 patterns1 b- M- c6 X4 A' l9 ~8 `: P
    在 gawk 程式里面,当 pattern 符合现在的输入记录(record),其
    4 t5 ^" q# u, v# S5 X相对应的 action 才会被执行。
    9 Q& w4 Q' j  Z3 o
    ) i7 W. V% h- w8 G5.1 Pattern的种类' ~( d3 ^+ Y) l+ A7 {/ N* K
    这里对 gawk 的各种 pattern 型式作一整理:' W; M: f: _$ ^0 ~7 c- j% h) `& {
    /regular expression/
    . ]. }5 I9 w7 z2 Z5 w- `$ d7 d一个 regular expression 当作一个 pattern。每当输入记录 (2 ^6 Q, E; l1 a& C' y
    record)含有 regular expression 就视为符合。, f7 _4 ^6 M+ F1 O" J: t' R9 s
    expression
    4 N  w* u* k3 t一个单一的 expression。当一个值不为 0 或一个字串不是空的,6 J& d! O$ U( d: }( k
    则可视为符合。
    5 a- y# T' X5 j2 apat1,pat2
    / f3 I* I7 e  q1 }; [一对的 patterns 以逗号分开,指定记录的□围。' x2 q$ s# t+ W5 l( B# U7 ^
    BEGIN
    8 M- t/ u! C! D- ]" D2 f0 yEND" R- d+ K) Q( X6 s0 S2 _! s
    这是特别的 pattern, gawk 在开始执行或要结束时会分别执行相% `! h5 G6 F/ V& R
    对应於BEGIN或END的 action。, ~2 f+ K/ y* ]: `
    null
    . q1 E4 j; S: g5 S这是一个空的pattern,对於每个输入记录皆视为符合pattern。7 |9 z" R. p5 i( A) V& R0 \7 P
    4 y( u  r! P  C2 B; Y' u- g
    5.2 Regular Expressions当作Patterns" \4 K$ D4 [. ~& d
    一个 regular expression 可简写为 regexp,是一种描述字串的方
    . _: d* c; c! d8 g  z  N法。一个 regular expression 以斜线('/')包围当作 gawk 的 pattern。; k3 Q+ ]5 R  w% B5 a
    如果输入记录含有 regexp 就视为符合。例如:pattern 为 /foo/,
    0 _5 P! O. [6 f& O3 T7 {对於任何输入记录含有'foo'则视为符合。
    ) r) G* x  r+ C& y+ E下面的例子会将含有'foo'的输入记录之第2个栏位印出。
    2 h- _0 A; {$ e7 g! \' D  mgawk '/foo/ {print $2}' BBS-list; g, m  r, ?+ z) B4 W! ?' k8 |. k* O
    结果如下:2 `" O/ [5 K9 _
    555-12346 j, ^) p. Y) v& U( h; y" X: t
    555-6699
    9 @/ \% Y; C: G. i* r; X555-6480
    " @1 w, F9 l$ P5 r3 C555-2127! f1 h) Y# Q, M5 l9 Y( T) N
    regexp 也能使用在比较的算式。
    1 L7 d/ G% o9 R) |+ t4 xexp ~ /regexp/: X' J* n; f% w
    如果 exp 符合 regexp,则结果为真(true)。) }7 F. h) P) P! e# t
    exp !~ /regexp/
    0 s1 k2 T+ I$ U如果 exp 不符合 regexp,则结果为真。
    ) i; r9 q3 h7 k$ U8 Y/ `
    * L2 n& t; n$ k! H5.3 比较的算式当作Patterns
    # F* Y$ V2 Q- t. v+ M3 f3 P2 @, c比较的 pattern 用来测试两个数字或字串的关系诸如大於、等於- `2 t2 Z2 e" b+ I' Z
    、小於。下面列出一些比较的pattern:
    $ }% m( w8 E/ u2 y1 sx<y 如果 x 小於 y,则结果为真。  h# x' s2 f% T: i8 r% m
    x<=y 如果 x 小於、等於 y,则结果为真。5 l: x2 `: Q& }
    x>y 如果 x 大於 y,则结果为真。
    7 u: N, o5 U' s4 f/ fx>=y 如果 x 大於、等於 y,则结果为真。
    3 T2 b1 x% A2 V, Z+ ux==y 如果 x 等於 y,则结果为真。
    $ f6 V; ?# y) f2 ?& T3 `, s  kx!=y 如果 x 不等於 y,则结果为真。2 h; q8 C& P4 W& v
    x~y 如果 x 符合 regular expression y,则结果为真。/ ^% A0 M; v2 @& b1 g
    x!~y 如果 x 不符合 regular expression y,则结果为真。7 C! O; b: K$ Y1 L% V& f, E
    上面所提到的 x 与 y,如果二者皆是数字则视为数字之间的比较,
    5 J/ k  @' c, _否则它们会被转换成字串且以字串的形式做比较。两个字串的比较,. Z" f( F+ U( \5 L
    会先比较第一个字元,然後比较第二个字元,依此类推,直到有不同% v# N7 `7 C+ q* V% a
    的地方出现为止。如果两个字串在较短的一个结束之前是相等,则视
    , o& {8 m  W$ B7 y为长的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。/ ^* n1 c: A: o
    0 X/ A, l9 M4 [1 @/ P- o
    5.4 使用布林运算的Patterns
    / `) v' ?! n6 `4 H' z一个布林(boolean) pattern 是使用布林运算"或"('||'),"及"
    / M9 B1 A. }" e/ c! f('&&'),"反"('!')来组合其它的pattern。# W( f8 }) c' K3 `% c
    例如:
    5 N9 b1 ?0 q- a0 V* i- d% {5 L; N9 ogawk '/2400/ && /foo/' BBS-list
    ; ~( a3 ?8 R3 H9 U% c3 x. P, ?gawk '/2400/ || /foo/' BBS-list
    ( C; X) i, H# A# ^: a( Z7 c1 p9 qgawk '! /foo/' BBS-list
    % R3 S3 C$ i$ f) F' N- ?0 V" w
    ; C, W: J+ n* Y3 Q7 k% s第六章 算式(Expression)作为Actions的叙述1 v7 b: k: k3 n$ _* M8 G
    算式(Expression) 是gawk程式里面action的基本构成者。; \0 v2 {3 p: M% X9 U* h9 \
    ! t" C" ?8 F/ }  _  d$ \
    6.1 算术运算2 ?% i2 G$ C0 U) b" _/ \
    gawk 里的算术运算如下所示:, W; A- j/ [  `9 k
    x+y 加/ m( z8 V$ ^' F) ]# H6 u4 L8 [9 K
    x-y 减2 Z, h5 \! ]! V! i- j! V; y
    -x 负
    % s. Y7 o4 ]5 f, j# |+x 正。实际上没有任何影响。
    2 D# @! b' q+ j5 U$ d2 B: mx*y 乘5 A: g0 n- H' j1 C
    x/y 除! i! I7 U! j9 h  Q9 D
    x%y 求馀数。例如 5%3=2。
    3 V5 Y* @/ b/ K+ {0 ix^y
    , B- T6 Y  H- o$ j6 Xx**y x 的 y 次方。例如2^3=8。. e  z, Z, ^1 C- _% I

    $ E2 ]6 @0 W* t3 Q6 k+ X* A8 y( k6.2 比较算式与布林算式
    & |" z$ L3 L1 k2 c8 x/ J9 e. Y比较算式 (comparison expression) 用来比较字串或数字的关系* j4 @2 O7 f" w& o3 ?$ Y
    ,运算符号与 C 语言相同。表列如下:
    9 h8 E1 L2 ~' |x<y- D4 E; H, x6 {7 E2 R5 y' F
    x<=y
      n7 k# g5 N, g' a' a) v9 L5 f+ [x>y5 d/ [4 {: C; |, K
    x>=y
    . e  O) ~8 Y) n' a5 W/ Nx==y
    & }% g: v8 b( D  C! n2 rx!=y. `( ^; S: B- }% B* [8 G3 N
    x~y
    ' x. y  `; e/ d8 D0 Y% _; ox!~y
    1 s. G  u2 H- o- s+ _  s比较的结果为真(true)则其值是 1。否则其值是 0。. v! ?, ~' n0 B# h- l0 Z
    布林算式(boolean expression)有下面三种:' X/ L4 A: `- p* m- G- N
    boolean1 && boolean2
    5 m% _5 |* F2 L# mboolean1 || boolean2
    ' w7 q5 \# M: M# y/ b+ T! boolean- e& q/ S( ?% b" A8 U* l
    & M9 J+ v3 N! @5 g  o
    6.3 条件算式(Conditional Expressions)- c; A* p3 B/ N; z3 i
    一个条件式算式是一种特别的算式,它含有3个运算元。' {7 X2 h0 ?7 q, g
    条件式算式与C语言的相同:
    * _* i6 u+ T. c1 x# o3 @selector ? if-true-exp : if-false-exp
    # H0 H4 z3 S- g$ a( n它有3个子算式。第一个子算式selector 首先会被计算。如果是真,
    0 x  @9 b7 @0 F: ]则if-true-exp会被计算且它的值变成整个算式的值。否则if-false-! L% s" k" D+ J; Q' k1 P
    exp 会被计算且它的值变成整个算式的值。& L* @; q" _# e0 W; z( w' _
    例如下面的例子会产生x的绝对值:
    * d7 Y8 a- k5 Xx>0 ? x : -x/ d1 `9 f6 h5 P% x9 M0 o7 N& \% k

    " _, C) P9 e7 C* i第七章 Actions里面的控制叙述& j  G2 @5 M2 `/ t5 |$ l
    在 gawk 程式里面,控制叙述诸如 if、while 等控制程式执行的流: ]# a# i% @; L/ K, Q! A
    程。在 gawk 里的控制叙述与 C 的类似。
    4 f! `; U# o6 o/ l$ K* w很多的控制叙述会包括其它的叙述,被包括的叙述称为 body。假
    . G" m3 a3 F  o5 j6 L如 body 里面包括一个以上的叙述,必须以大括弧 { } 将这些叙述括起$ \+ [) s* i8 _# k/ {) z) K, }
    来,而各个叙述之间需以换行(newline)或分号隔开。
    4 u! ]9 @% b* M' e, F( Z5 E
    & Z8 }  j( y/ p$ J: w7.1 if 叙述
    0 e  X; Q0 V$ e1 q  P" `+ o/ [if (condition) then-body [else else-body]# `8 p# e  ?( F
    如果 condition 为真(true),则执行 then-body,否则执行 else-body。, a3 ^* t! O, |1 Z6 G) p
    举一个例子如下:
    . q; J6 x3 [) C( j& e5 {if (x % 2 == 0)- p- W* p+ R! p2 \4 P4 w  C
    print "x is even") ?! n9 X$ e) I$ d
    else
    - v* N6 |8 ]" F$ ~/ n2 _# vprint "x is odd", l7 n/ O5 I9 ~* K
    5 q  h8 R1 b8 c$ K
    7.2 while 叙述
    , g/ \& l# ?4 a2 T4 pwhile (condition)
    0 m3 T. k, j# r% B( Wbody
    3 I* Y9 w: V  [$ h- l3 J# Awhile 叙述做的第一件事就是测试 condition。假如 condition 为真则% A% N5 G3 M1 x! k
    执行 body 的叙述。body 的叙述执行完後,会再测试 condition,假如0 r/ n& }6 b8 e# b( e; ?
    condition 为真,则 body 会再度被执行。这个过程会一直被重复直到
    1 q( z$ Q+ _8 c8 q# b1 acondition 不再是真。如果 condition 第一次测试就是伪(false),则- q  E/ q; H& W$ A1 V" A
    body 从没有被执行。) r( A& e- r/ L6 s
    下面的例子会印出每个输入记录(record)的前三个栏位。
    # g; E9 R/ u/ d* ?! {/ Xgawk '{ i=1
    6 ]. n! w/ }4 f3 _9 rwhile (i <= 3) {+ x* q  l7 T  k4 \5 n
    print $i5 k4 \6 O3 s" @& x( t
    i++2 G& [8 ~2 J* }& a
    }
    / X& N; u' u) J1 l}'  s. _" t/ F' O) M) U' X
    ' C5 W, @. o. {: N
    7.3 do-while 叙述3 O& p0 G( l+ M& }' [6 A' Y
    do
    0 \5 N% I6 y9 V" W3 c* tbody
    - b! T( U9 d  O: k$ R1 z3 lwhile (condition)
    6 u/ s% W& B/ B. W# Z! P这个 do loop 执行 body 一次,然後只要 condition 是真则会重复执行 body。' `0 Y4 q; U4 ~; @6 G7 s
    即使开始时 condition 是伪,body 也会被执行一次。
    2 [/ O* ]; j$ i: s$ j下面的例子会印出每个输入记录十次。5 n1 T5 U# O! ~: c# m! ^) M' u
    gawk '{ i= 17 G- e; b( v+ q* n
    do {
    2 _7 p( x2 g8 M7 y! ]3 jprint $0  N8 I  a3 ^9 h: m) n# B
    i++
    & E$ Z$ T1 Q' l8 [6 |+ x} while (i <= 10)
      B, ~9 f- N. h}'  {1 d! O8 C- I* n0 e7 `) p+ G: Q% [

      V  Y4 I5 ?; y7.4 for 叙述4 N* R& T7 n8 R1 i  {
    for (initialization; condition; increment)' F9 A5 S' ?& h; v* ?
    body
    : T( z: Y4 y" H: q- g此叙述开始时会执行initialization,然後只要 condition是真,它5 l3 K' f; x1 N( x5 D6 s& [/ r* k
    会重复执行body与做increment 。
    5 m! \4 d$ L$ {  T下面的例子会印出每个输入记录的前三个栏位。7 C3 L1 y6 a0 I# i
    gawk '{ for (i=1; i<=3; i++)
    " \& r# w. K- E7 U. }5 mprint $i9 N, }- |( j% T
    }'
    - R' z6 v% L% q& K5 t- K; w8 _* g$ |% S
    7.5 break 叙述
    6 k8 B) O- L- P+ Y, Obreak 叙述会跳出包含它的 for、while、do-while 回圈的最内层。
    9 X2 W0 v+ p* {下面的例子会找出任何整数的最小除数,它也会判断是否为质数。' X# S4 l. ^+ E
    gawk '# find smallest divisor of num0 B3 B5 e2 {( I) V+ T' P
    { num=$1
    # a; [3 l  |; F* i/ N2 Lfor (div=2; div*div <=num; div++)$ I3 b3 d2 _0 a$ m( q
    if (num % div == 0)/ K" D. f- g6 a0 x2 n
    break
    ) J* B0 k" a4 gif (num % div == 0); |& b" B7 Z/ @2 C% S4 p
    printf "Smallest divisor of %d is %d\n", num, div/ O  h: r9 x" N9 ~. g0 z* B4 w+ f
    else- x  [9 n% [0 Y% Y9 X
    printf "%d is prime\n", num }'
    , D  [7 I7 f4 |7 ?! a3 c* f+ F7 y
    2 Q( R3 w2 r, a; L7.6 continue 叙述* f& K2 }7 x6 ?8 Y% y3 c
    continue 叙述使用於 for、while、do-while 回圈内部,它会跳" e; T' M$ ?/ A/ }( n9 B
    过回圈 body 的剩馀部分,使得它立刻进行下一次回圈的执行。1 X1 c- S( M/ V1 {' b
    下面的例子会印出 0 至 20 的全部数字,但是 5 并不会被印出。
    6 u+ D  D: I2 C6 |gawk 'BEGIN {5 V, o) u" n0 p- E4 m
    for (x=0; x<=20; x++) {
    % @! w+ Z# u. p- `3 Nif (x==5)
    - P/ f1 f& D, ^0 b$ b3 Z& s: vcontinue3 U# Z  o* P3 Z3 R
    printf ("%d",x)+ M% Q6 u9 J9 k+ H
    }7 ?7 E. G$ N- M1 A5 C- p
    print ""! m& X4 K, b/ D) M3 H; }9 s8 T: z- V
    }'
    $ ~8 g1 r; j  K7 ]6 [* \- I7 s9 O( g
    7.7 next 叙述、next file 叙述、exit 叙述
    . \2 d& d) O3 w( ?1 pnext 叙述强迫 gawk 立刻停止处理目前的记录(record)而继续下一
    . v; r: c5 e- X5 O/ i" f个记录。' e. Z0 v( w8 w3 H% ]" W
    next file 叙述类似 next。然而,它强迫 gawk 立刻停止处理目前
    * d4 d3 u4 }! |* Z  a, p) m( Z的资料档。
    + V. U- i; |* x: i3 R5 g+ P- @% aexit 叙述会使得 gawk 程式停止执行而跳出。然而,如果 END 出现
    2 l3 l! ?( L2 Q5 m+ B0 k3 `,它会去执行 END 的 actions。7 C! [6 s# t9 ^
      ^* [% ^& m9 V- B  E! h0 Q' L; H
    第八章 内建函式(Built-in Functions)
    $ z  i# j( a7 \$ P: K6 e: U内建函式是 gawk 内建的函式,可在 gawk 程式的任何地方呼叫内建
    1 A+ w6 c2 V; U+ [6 R: i' s函式。3 c2 V7 i& k  x7 }( k: R

    # w3 S7 N  ~$ N1 W+ f7 F8.1 数值方面的内建函式
    ' X* v5 O* n; n. G1 v, Q0 kint(x) 求出 x 的整数部份,朝向 0 的方向做舍去。例如:int(3.9)
    ( t. z" S* A# h6 a是 3,int(-3.9) 是 -3。- J. I+ ~0 q! e; u/ @
    sqrt(x) 求出 x 正的平方根值。例 sqrt(4)=2) k" N% K; U) S# @# }# _
    exp(x) 求出 x 的次方。例 exp(2) 即是求 e*e 。
    : E  R( ^* h9 v: Qlog(x) 求出 x 的自然对数。
    & x2 ]0 z+ e9 Q4 x2 j  }, z' Jsin(x) 求出 x 的 sine 值,x 是弪度量。3 _; Z) }+ x+ b  Y9 N$ @8 F  B
    cos(x) 求出 x 的 cosine 值,x 是弪度量。) W# v# S4 B+ Q' a2 f. ?
    atan2(y,x) 求 y/x 的 arctangent 值,所求出的值其单位是弪度量。3 ^: G! g4 i% m
    rand() 得出一个乱数值。此乱数值平均分布在 0 和 1 之间。这个1 x' e4 ?" V* {/ u
    值不会是 0,也不会是 1。
    + ^9 N; e- ]7 ^9 H  s# u: B每次执行 gawk,rand 开始产生数字从相同点或 seed。8 y' f: g6 l* v, o# N' w$ x1 Q
    srand(x) 设定产生乱数的开始点或 seed 为 x。如果在第二次你设
    ; l" @- \# k2 {# |4 A定相同的 seed 值,你将再度得到相同序列的乱数值。
    ( Q; l% V" F& h: G如果省略引数 x,例如 srand(),则现在的日期、时间会/ G: h% v' D  a+ o+ |8 u. s% m
    被当成 seed。这个方法可使得乱数值是真正不可预测的。
    6 t0 B; R$ @0 d* x0 T, ~$ J  nsrand 的传回值(return value)是前次所设定的 seed 值。7 D7 j% S9 N5 F- x2 M3 R" ^- @
    5 q, z7 }; B) U% O) `. E/ b
    8.2 字串方面的内建函式
    4 b4 s( r7 ^7 I/ d! rindex(in, find)
    . o+ j. l' d$ D. ~- {' Z* D5 i7 a它会在字串 in 里面,寻找字串 find 第一次出现的地方,传回值是
    % ?9 b# I( F: B( r' Y字串 find 出现在字串 in 里面的位置。如果在字串 in 里面找不到字3 c$ H8 H0 [' {  C) S0 |# ~
    串 find,则传回值为 0。+ m) F8 J9 c. {4 e5 V' I, ~
    例如:5 H+ r5 ?6 A, G7 k% V- P
    print index("peanut","an")& G+ {9 }4 g2 P) v
    会印出 3。8 X' e8 F- ]6 d0 Z" [0 X/ u/ ^/ _
    length(string)% L+ Z4 ^, i- y) d
    求出 string 有几个字元。
    0 W0 V  c1 [  v' ]! L+ y' v例如:: k2 t( i+ n: H5 s3 O6 V
    length("abcde"), D( _  f5 ^' U3 T
    是 5。
    ' k3 ~& v; q: u+ f( k; [" K4 ^match(string,regexp)
    - d* S& S* u- u/ Umatch 函式会在字串 string 里面,寻找符合 regexp 的最长、最靠
    4 ^9 l* J' g# U$ g" a左边的子字串。传回值是 regexp 在 string 的开始位置,即 index
      n1 F3 e- D2 P' B8 O值。$ w, ~! V6 g2 I
    match 函式会设定内在变数 RSTART 等於 index,它也会设定内在变# g9 f0 q, P- W, v$ }- W
    数 RLENGTH 等於符合的字元个数。如果不符合,则会设定 RSTART 为7 C5 y3 n& G3 _. \1 T9 S- Z/ R
    0、RLENGTH 为 -1。
    & t6 P+ I/ C5 c2 L8 T3 Isprintf(format,expression1,...)& [! r2 |' N/ [
    举 printf 类似,但是 sprintf 并不印出,而是传回字串。
    % k8 D6 Q/ ]4 T" Z例如:* Q  C7 Y9 C# ?7 ^
    sprintf("pi = %.2f (approx.)',22/7)& J9 g7 K% P+ G$ B* E3 w
    传回的字串为"pi = 3.14 (approx.)"( A( V  V; p$ X$ K0 ?- @: J; \$ p
    sub(regexp, replacement,target)
    , N; W9 x+ t- }& v在字串 target 里面,寻找符合 regexp 的最长、最靠左边的地方,$ o/ O& z# }5 y* q
    以字串 replacement 代替最左边的 regexp。
    2 W4 P/ j6 v+ Z例如:
    ) R/ t, J7 I2 l( ?8 kstr = "water, water, everywhere"
    * s% T+ c% p6 P3 a- ksub(/at/, "ith",str)( k. b* c: U1 L5 A6 Q, J6 P
    结果字串str会变成
    + J, h  m% \! }# R"wither, water, everywhere"
    , A/ P! l5 _3 r) d9 W  kgsub(regexp, replacement, target)
    * B7 U. p2 ^: }  h) Lgsub 与前面的 sub 类似。在字串 target 里面,寻找符合 regexp 的
    ' c5 d5 R9 c$ Y! y. r9 L. M所有地方,以字串 replacement 代替所有的 regexp。
    " \) j3 {* G2 R, a( g例如:
    7 i$ k) e& i8 e2 _# H+ ]# e2 xstr="water, water, everywhere"0 R9 b! h) A5 S$ V6 @
    gsub(/at/, "ith",str)
    / J8 z: o4 \5 `: q. f结果字串str会变成
    8 m6 y( I$ b3 m5 Y8 V'wither, wither, everywhere"
    + C+ T. C1 e1 S; C% M- Wsubstr(string, start, length)% p* K5 W# C% R+ E9 Q$ y+ |
    传回字串 string 的子字串,这个子字串的长度为 length 个字元,
    ; ], b8 O' N3 d; ~& @从第 start 个位置开始。
    7 ^  {0 g7 W2 S- q* `+ Z例如:
    / n$ [& F- f1 i- ^  c5 \# Wsubstr("washington",5,3)
    & [" @; E& @4 j9 T6 A) t传回值为"ing"
      b0 }, P- D( A' x, E如果 length 没有出现,则传回的子字串是从第 start 个位置开始/ J, w  K& d( d
    至结束。1 A/ r$ P2 Z, [! q: i1 v
    例如:
    * g5 V, |7 [2 Z. `$ q0 n$ N9 Usubstr("washington",5)6 S* ~  {* g6 t! ?/ H" z# W
    传回值为"ington"3 D. S, u, }9 U' j& O
    tolower(string)5 j# I, }; K6 n; u
    将字串string的大写字母改为小写字母。: i% C; h1 K8 C8 s0 u& Z
    例如:2 b7 J" Z7 o& h
    tolower("MiXeD cAsE 123")
    3 `, c2 X% O- e3 \传回值为"mixed case 123"; Z1 P9 \& ]( ]+ q- N4 I
    toupper(string)
    - z  u8 `* M3 @% ?. I将字串string的小写字母改为大写字母。- f( P( Q; R, x2 v* b6 h
    例如:* Q9 a( W5 ]- P$ J
    toupper("MiXeD cAsE 123")5 N; v7 u3 \, |/ `, f2 x
    传回值为"MIXED CASE 123"% n1 s0 `# m6 c+ {( k* C2 p. b4 e( O5 D

    " U6 U9 O1 `2 F% |! |' L/ l8.3 输入输出的内建函式+ o$ x) d7 p5 ~) L
    close(filename)
    0 q" U# I. a: O5 _; I将输入或输出的档案 filename 关闭。
    * c* B- i6 M6 g. B+ Zsystem(command)
    1 p) m- U9 w8 u4 {  J$ x此函式允许使用者执行作业系统的指令,执行完毕後将回到 gawk
    ' m9 X  Z0 @! H. w9 B# `5 f程式。. c# D! D3 o) ?5 C
    例如:
    / @$ i" k2 x; O' r5 [5 NBEGIN {system("ls")}0 W$ G3 n& v; o) }; a0 Q! _

    . ^: F! {* ^+ k0 w4 [$ _第九章 使用者定义的函式(User-defined Functions)
      S0 o+ u% i% j& x0 L复杂的 gawk 程式常常可以使用自己定义的函式来简化。呼叫使用
    ) t- M9 L, \5 W3 }2 x4 T& ?者定义的函式与呼叫内建函式的方法一样。% Y! f  x+ x, Y3 I# ~7 C8 {- x! f$ p) Z
    1 Z8 s3 ~( M/ W8 n! T
    9.1 函式定义的格式. ^# o! P# h- B4 r  a3 \$ c
    函式的定义可以放在 gawk 程式的任何地方。
    3 Z, A4 r* e' w' m% ]一个使用者定义的函式其格式如下:
    9 G* E; d6 z8 r. H+ ]function name (parameter-list) {
    4 }) O, K% N- F3 ^body-of-function+ v* B4 i2 V! T! \0 d
    }
    7 Y/ S0 f: ^0 y, g. |name 是所定义的函式之名称。一个正确的函式名称可包括一序列的字
    : h+ ~- w2 K# A母、数字、下标线 (underscores),但是不可用数字做开头。
    $ P5 W& M$ s% n% O1 i8 uparameter-list 是列出函式的全部引数(argument),各个引数之
    % b* J4 A: V# }; R/ r间以逗点隔开。
    % d- b( x& O2 A2 _body-of-function 包含 gawk 的叙述 (statement)。它是函式定义$ S9 K$ A- G6 F( S* D
    里最重要的部份,它决定函式实际要做何种事。
    0 H5 k" p; ~' U9 o1 _( D! i) o. n
    9.2 函式定义的例子
    9 n8 D- _) H2 r- G7 O下面这个例子,会将每个记录的第一个栏位之值的平方与第二个' F$ k& b! Y; D) I4 _
    栏位之值的平方加起来。
    . s8 h% `( @+ N  H6 o{print "sum =",SquareSum($1,$2)}. e, w2 D' X6 D6 q; V
    function SquareSum(x,y) {$ P9 Z1 V5 `; _  l
    sum=x*x+y*y5 T) J6 H  k8 {" N
    return sum7 H, A+ b5 X% |" w8 a1 ?
    }
    ! Q+ D2 z  Y7 Z5 _9 g, V7 Q% O
    / @! s' X1 U4 H" a第十章 □例, K6 O2 W% w6 L' R
    这里将列出 gawk 程式的一些例子。' [1 D) u, V7 B# n" X1 y9 z
    gawk '{if (NF > max) max = NF}
    - U8 q- a$ I( a0 S! ?$ t9 FEND {print max}'
    " r: ~, Y' r6 a  c8 F此程式会印出所有输入行之中,栏位的最大个数。
    . p8 S; r* ~' p8 m1 wgawk 'length($0) > 80'
    * u9 `6 l) p" J. e此程式会印出一行超过 80 个字元的每一行。此处只有 pattern 被
    : H9 |# G9 S/ U$ U3 Y$ t列出,action 是采用内定的 print。! G% n6 t6 d, U2 |+ ^8 j6 G
    gawk 'NF > 0'
    - n3 R- A8 j1 _3 g1 b/ ~2 @对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简
    + g# Z8 L3 o* `, R+ @5 B; c& |5 q单的方法,将一个档案里的所有空白行删除。9 c8 _  @: K3 M, u& L8 z
    gawk '{if (NF > 0) print}'
      F, d+ x' e$ Z- X. @( Y, R对於拥有至少一个栏位的所有行,此程式皆会印出。这是一个简; }( N2 }8 r0 I; f& w
    单的方法,将一个档案里的所有空白行删除。
    * ]- s7 P) L& X3 V6 A/ Ygawk 'BEGIN {for (i = 1; i <= 7; i++)
    5 p" Y/ f+ P: j3 Tprint int(101 * rand())}'- M+ |/ w2 k' P9 w
    此程式会印出□围是 0 到 100 之间的 7 个乱数值。
    5 e4 p  N; D  J- c' e  pls -l files | gawk '{x += $4}; END {print "total bytes: " x}'
    9 l; `9 I( {$ {  s3 k! B: G# ?此程式会印出所有指定的档案之bytes数目的总和。! i4 S. g6 `0 @0 h- m: l: f
    expand file | gawk '{if (x < length()) x = length()}
    4 z! V4 G4 A, @( [" X, q  l' sEND {print "maximum line length is " x}'
    ; \4 O5 k8 J) x; G3 a1 R4 K) _此程式会将指定档案里最长一行的长度印出。expand 会将 tab 改
    ; T' u' R5 z# {成 space,所以是用实际的右边界来做长度的比较。7 t  f" p$ q" q1 ?: p
    gawk 'BEGIN {FS = ":"}8 z  p) A+ V2 c! U) g% e2 V( M; s
    {print $1 | "sort"}' /etc/passwd9 d8 D, i6 x5 Q) @1 G
    此程式会将所有使用者的login名称,依照字母的顺序印出。1 `4 C: r, l2 }, G" R; R
    gawk '{nlines++}
    $ ^  B( C! l9 r/ t, hEND {print nlines}'
    1 `# s6 h- d" F1 o2 P, A此程式会将一个档案的总行数印出。) w' s. b6 `, y5 |* k4 e; E0 ^6 H
    gawk 'END {print NR}'" _9 N$ ^, H$ F6 Z1 F. {4 V/ `, u
    此程式也会将一个档案的总行数印出,但是计算行数的工作由gawk
    8 L8 F8 t4 \* ^2 g( `% ~8 D来做。
      z9 i! ~# }7 ^) \gawk '{print NR,$0}'
      s7 R4 N7 Q- x# r1 z" x# _8 C此程式印出档案的内容时,会在每行的最前面印出行号,它的功
    # ~* }  F6 u* a) m. E) z& x能与 'cat -n' 类似。
    # y3 j2 j6 _6 ~% Z  o  }# e
    , W$ |, y( l% ?$ R" G/ M第十一章 结论
    4 O5 h3 Z4 h+ }4 egawk 对於资料的处理具有很强的功能。它能够以很短的程式完成4 }' e$ E$ B( y" s2 y; j. }
    想要做的事,甚至一或二行的程式就能完成指定的工作。同样的一件4 A* F6 V: |. \! f2 T# K
    工作,以 gawk 程式来写会比用其它程式语言来写短很多。
    2 w+ E2 h" l. i; a; n! |/ ngawk 是 GNU 所做的 awk,它是公众软体(Public Domain) 可免费使5 |5 g* E# K5 N' _) M0 H$ J- s3 [
    用。
    "真诚赞赏,手留余香"
    还没有人打赏,支持一下
    楼主热帖

    相关帖子

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

    该用户从未签到

    尚未签到

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

    本版积分规则

    招聘斑竹

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

    GMT+8, 2026-4-12 16:34

    Powered by Discuz! X3.5 Licensed

    © 2001-2026 Discuz! Team.

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