zoukankan      html  css  js  c++  java
  • Shell 学习—AWK介绍

    Shell 学习—AWK

    = = = 安装awk

    root@kiki-desktop:~/shell# apt-get install gawk gawk-doc

    = = = awk 是一种程序语言. 它具有一般程序语言常见的功能.

    = = =.因awk语言具有某些特点,

    如 : 使用直译器(Interpreter)不需先行编译;

     变量无类型之分(Typeless), 可使用文字当数组的下标(Associative Array)...等特色. 因此, 使用awk撰写程序比起使用其它语言更简洁便利且节省时间.

     awk还具有一些内建功能, 使得awk擅于处理具数据行(Record), 字段(Field)型态的资料;

     此外, awk内建有pipe的功能, 可将处理中的数据传送给外部的 Shell命令加以处理, 再将Shell命令处理后的数据传回awk程序, 这个特点也使得awk程序很容易使用系统资源.

    = = =  awk程序的主要结构:

    awk程序中主要语法是 Pattern { Actions}, 故常见之awk 程序其型态如下 :

    Pattern1 { Actions1 }

    = = =  Actions 是什么?

    Actions 是由许多awk指令构成. 而awk的指令与 C 语言中的指令十分类似.

    例如 :

    awk的 I/O指令 : print, printf( ), getline...

    awk的 流程控制指令 : if(...){..} else{..}, while(...){...}...

    = = =  例子

    有时语法 Pattern { Actions }中, Pattern 部分被省略,只剩 {Actions}.这种情形表示 "无条件执行这个 Actions".

    50 > 23 {print "Hello! The word!!" }

    "banana" ~ /123/ { print "Good morning !" }

    # awk '{print $2,$3*$4}' emp

    UNIX命令行上, 执行awk的语法为:

    $awk 'awk程序' 欲处理的资料文件文件名

    # cat file1 | awk -F , {'print $1,$2'}

    = = =  例如 : awk 从资料文件 emp.dat 中读入第一笔数据行

    "A125 Jenny 100 210" 之后, 程序中:

    $0 之值将是 "A125 Jenny 100 210"

    $1 之值为 "A125"

    $2 之值为 "Jenny"

    $3 之值为 100

    $4 之值为 210

    $NF 之值为 4

    $NR 之值为 1

    $FILENAME 之值为 "emp.dat"

    = = =  awk的工作流程 :

    执行awk时, 它会反复进行下列四步骤.

    自动从指定的数据文件中读取一个数据行.

    自动更新(Update)相关的内建变量之值. 如 : NF, NR, $0...

    依次执行程序中 所有 的 Pattern { Actions } 指令.

    当执行完程序中所有 Pattern { Actions } 时, 若数据文件中还有未读取的数据, 则反复执行步骤1到步骤4.

    awk会自动重复进行上述4个步骤, 使用者不须于程序中编写这个循环 (Loop).

    = = =  linux中 文本以空格分隔的行就可以默认操作

                                以其他分隔如, ;等等,就可以用awk –f 操作

    dengfang,0Rgbo2Kyn0hms

    huyibao,0R1d4zCYO3qxk

    dengfeng,0RUsQ9pz6kBPs

    gongfangping,0Ru/KhW.8Ove6

    liucaigeng,0Rekdi5B0sWfU

    = = =  print 的参数间彼此以 "," (逗号) 隔开, 印出数据时彼此间会以空白隔开.

    例一,选择符合指定条件的记录

    组装部门员工调薪5%,(组装部门员工之ID以"A"开头)

    所有员工最后之薪资率若仍低于100, 则以100计.

    编写awk程序打印新的员工薪资率报表.

    原文件:

    A125 Jenny 100 210

    A341 Dan 110 215

    P158 Max 130 209

    P148 John 125 220

    A123 Linda 95 210

    [root@kiki-desktop:~/shell# cat adjust1.awk

    $1 ~ /^A.*/ {$3*=1.05} $3<100 {$3=100}

    {printf("%s %8s %d ",$1,$2,$3)}

    root@kiki-desktop:~/shell# cat emp

    A125 Jenny 100 210

    A341 Dan 110 215

    P158 Max 130 209

    P148 John 125 220

    A123 Linda 95 210

    root@kiki-desktop:~/shell# awk -f  adjust1.awk  emp

    A125    Jenny 105

              100

    A341      Dan 115

              100

    P158      Max 130

              100

    P148     John 125

              100

    A123    Linda 100

    例二,统计各科修课人数,并印出结果

    此为一学生注册的资料文件; 第一栏为学生姓名, 其后为该生所修课程.

    Mary O.S. Arch. Discrete

    Steve D.S. Algorithm Arch.

    Wang Discrete Graphics O.S.

    Lisa Graphics A.I.

    Lily Discrete Algorithm

    .

    建立如下程序,并取名为 course.awk:

    { for( i=2; i <= NF; i++) Number[$i]++ }

    END{for(course in Number) printf("%10s %d ", course, Number[course] )}

    执行下列命令 :

    $awk -f course.awk reg.dat

    执行结果如下 :

      Graphics 2

          O.S. 2

      Discrete 3

          A.I. 1

          D.S. 1

         Arch. 2

     Algorithm 2

    解说:指令中END 为awk之保留字, 为 Pattern 的一种.

    END 成立(其值为true)的条件是: "awk处理完所有数据, 即将离开程序时. "

    平常读入数据行时, END并不成立, 故其后的Actions 并不被执行;

    唯有当awk读完所有数据时, 该Actions才会被执行 ( 注意, 不管数据行有多少笔, END仅在最后才成立, 故该Actions仅被执行一次.)

    BEGIN 与 END 有点类似, 是awk中另一个保留的Pattern.

    唯一不同的是: "以 BEGIN 为 Pattern 的 Actions 于程序一开始执行时, 被执行一次."

    = = = awk中数组的特性

    使用字符串当数组的下标(index).

    使用数组前不须宣告数组名及其大小.

    例如: 希望用数组来记录 reg.dat 中各门课程的修课人数.

    这情况,有二项信息必须储存:

    (a) 课程名称, 如: "O.S.","Arch.".. ,共有哪些课程事先并不明确.

    (b)各课程的修课人数. 如: 有几个人修"O.S."

    在awk中只要用一个数组就可同时记录上列信息. 其方法如下:

    使用一个数组 Number[ ] :

    以课程名称当 Number[ ] 的下标.

    以 Number[ ] 中不同下标所对映的元素代表修课人数.

    例如:

    有2个学生修 "O.S.", 则以 Number["O.S."] = 2 表之.

    若修"O.S."的人数增加一人,则 Number["O.S."] = Number["O.S."] + 1 或 Number["O.S."]++ .

    例三,写一个awk程序来打印出线上人数.

    将下列程序建文件, 命名为 count.awk

    BEGIN {

    while ( "who" | getline ) n++

    print n

    }

    并执行下列命令 :

    awk -f count.awk

    执行结果将会印出目前在线人数

    getline var

    pipe 变量

    变量 var(var省略时,表示置于$0)

    例四,重定向输出到文件

    root@kiki-desktop:~/shell# cat arr.dat

    1034 7:26

    1025 7:27

    1101 7:32

    1006 7:45

    1012 7:46

    1028 7:49

    1051 7:51

    1029 7:57

    1042 7:59

    1008 8:01

    1052 8:05

    1005 8:12

    root@kiki-desktop:~/shell# cat reformat1.awk

    BEGIN { print " ID Number Arrival Time" > "today_rpt1"

    print "===========================" > "today_rpt1"

    }

    { printf(" %s %s ", $1,$2 ) > "today_rpt1" }

    root@kiki-desktop:~/shell#

    root@kiki-desktop:~/shell#

    root@kiki-desktop:~/shell# awk -f reformat1.awk arr.dat

    root@kiki-desktop:~/shell#

    = = = awk 中如何利用系统资源

    注 : awk input 指令只有 getline 一个.

    awk output 指令有 print, printf() 二个.

    在a 语法中, awk所输出的数据将转送往 Shell , 由 Shell 的命令进行处理.以上例而言, print 所输出的数据将经由 Shell 命令 "sort -k 1" 排序后再送往屏幕(stdout).

    上列awk程序中, "print$1, $2" 可能反复执行很多次, 其输出的结果将先暂存于 pipe 中,等到该程序结束时, 才会一并进行 "sort -k 1".

    须注意二点 : 不论 print $1, $2 被执行几次, "sort -k 1" 的执行时间是 "awk程序结束时",

    [a. 语法] awk output 指令 | "Shell 接受的命令"

    ( 如 : print $1,$2 | "sort -k 1" )

    例5,

    root@kiki-desktop:~/shell# awk '

    > BEGIN{

    > system("date > date.dat")

    > getline < "date.dat"

    > print "Today is ", $2, $3

    > }

    > '

    Today is  Jan 26

    = = = = 执行 awk 程序的几种方式= = = =

    若欲执行该awk程序, 来印出文件 today_rpt1 及 today_rpt2 的内容时,

    必须于 UNIX 的命令行上执行下列命令 :

    方式一 awk -f mydump.awk today_rpt1 today_rpt2

    方式二 awk '{print}' today_rpt1 today_rpt2第二种方式系将awk 程序直接写在 Shell 的命令行上, 这种方式仅适合较短的awk程序.

    方式三 建立如下之 shell script, 并取名为 mydisplay, $ ./mydisplay today_rpt1 today_rpt2

    #!/bin/sh

    # 注意以下的 awk 与 ' 之间须有空白隔开

    awk '

    {print}

    ' $*

    # 注意以上的 ' 与 $* 之间须有空白隔开

    例5,$ ./mydisplay  #(未接任何数据文件文件名)

    将会发现: 此后键入的任何数据将逐行复印一份于屏幕上. 这情况不是机器当机 ! 是因为awk程序正处于执行中. 它正按程序指示, 将读取数据并重新dump一次; 只因执行时未指定数据文件文件名, 故awk 便以stdin(键盘上的输入)为数据来源. 读者可利用这个特点, 设计可与awk即时聊天的程序.

    root@kiki-desktop:~/shell# ./mydisplay

    kiki

    kiki

    kiki

    kiki

    mina

    mina

    例6,改变 awk 切割字段的方式 & 自定义函数

    范例 : ] 承接 6.2 的例子, 若八点为上班时间, 请加注 "*"于迟到记录之前, 并计算平均上班时间.

  • 相关阅读:
    ASP.NET 动态创建文本框 TextBox (add TextBox to page dynamically)
    SQL Server 行列转换
    NPOI把Excel导入到数据库
    Net操作Excel(终极方法NPOI)
    mongdo通用类(C#版)
    ORACLE 定时执行存储过程
    C# Excel导入、导出
    网络爬虫+HtmlAgilityPack+windows服务从博客园爬取20万博文
    Git初级使用教程
    asp.net+swfupload 多图片批量上传(附源码下载)
  • 原文地址:https://www.cnblogs.com/bigbean/p/3661554.html
Copyright © 2011-2022 走看看