gawk入门及进阶

1 篇文章 0 订阅
1 篇文章 0 订阅

gawk入门及进阶

GNU awk 

    文本处理三工具:
        grep 、egrep、fgrep :文本过滤工具,pattern
        sed :行编辑器
            模式空间 、保持空间 
        awk :报表生成器,格式化文本输出;

        AWK :Aho,Weinberger,Kernighan,三位作者,在Unix上使用

        New AWK :NAWK 

        gwak :GNU awk ,在Linux上使用



    gawk : pattern scanning and processing language

        基本用法 :gawk [option] 'program' FILE ...
            program :PATTERN{ACTION STATEMENTS}
                语句之间用分号分隔


            选项: 
                -F :指明输入时用到的字段分隔符;
                -v var=value :自定义变量;


        1. print

            print item1,item2,...

            要点:
                (1) 逗号作为分隔符,默认输出结果的分隔符是一个空白字符;
                (2) 输出的各item可以是字符串,也可以是数值,当前记录的字段、变量或awk的表达式; 
                (3) 如省略item,相当于print $0,即输出全部;

        2. 变量:【注意】引用变量不要加$符号
            2.1 内建变量
                FS  :input field seperator,默认为空白字符;
                OFS :output field seperator,默认为空白字符;
                        如:]# awk -v FS=':' -v OFS=',' '{print $1,$2}' /etc/passwd
                         ]# awk -v RS=':' '{print}' /etc/passwd

                RS  :input record seperator,输入时的换行符;
                ORS :output record seperator,输出时的换行符;
                        如:]# awk -v RS=':' -v ORS=' ' '{print}' /etc/passwd
                        root x 0 0 root /root /bin/bash
                        bin x 1 1 bin /bin /sbin/nologin

                NF :number of field,字段数量
                        如:]# awk -v OFS='********' '{print NF,$NF,$0}'

                    【注意】引用变量不要加$符号:
                            此处{print NF}与{print $NF} 二者的输出效果不同,NF代表本行有多少个字段,$NF代表将NF的值作为变量名。
                            最终的执行效果为:输出本行的字段数量和本行最后一个字段。

                NR :number record , 处理的行数,如果有多个文件则一起计数
                FNR:file number recor ,多个文件分别计数
                        例1 :输出处理两个文件的行数,两个文件行数一起计算
                        ]# awk '{print NR}' /etc/fstab /etc/issue
                        例2 :输出处理两个文件的行数,两个文件行数单独分别计算
                        ]# awk '{print FNR}' /etc/fstab /etc/issue

                FILENAME :  当前处理的文件的文件名
                        例1 :]# awk '{print FNR,FILENAME}' /etc/fstab /etc/issue

                ARGC :命令行参数的个数;
                ARGV :数组,保存的是命令行所给定的各参数;
                        如:
                        ]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
                        3
                        ]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue
                        awk
                        ]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue
                        /etc/fstab                          
                        ]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue
                        /etc/issue  


            2.2 自定义变量 【注意】引用变量不要加$符号
                (1) -v var=value

                    变量名区分字符大小写:
                        如:]# awk -v test="hello awk" 'BEGIN{print test}'
                            hello awk

                (2) 在program中直接定义
                        如:]# awk 'BEGIN{test="hello awk";print test}'
                            hello awk


        3. printf 命令

            格式化输出 :printf FORMAT,item1,item2,...

                (1) FORMAT必须给出;
                (2) 不会自动换行,需要显式给出换行控制符,\n
                (3) FORMAT中需要分别为后面的每个item指定一个格式化符号;

                格式符:
                    %c  :显示字符的ASCII码
                    %d,%i:显示十进制整数
                    %e,%E :科学计数法数值显示
                    %f  :显示为浮点数
                    %g,%G : 以科学计数法或浮点形式显示数值
                    %s :显示字符串
                    %u :无符号整数
                    %% :显示%自身

                    如:]# awk -F: '{printf "Username: %s---UID:%d\n",$1,$3}' /etc/passwd
                        Username: root---UID:0
                        Username: bin---UID:1

                修饰符:在格式符前面加修饰的符号,控制格式的显示机制
                    #[.#]:第一个数字控制显示的宽度(默认右对齐):第二个#标识小数点后的精度(可省略)
                        %3.1f
                            如:
                            ]# awk  -F: '{printf "Username:%10s     UUID:%7.1f\n",$1,$3}' /etc/passwd 
                            Username:       ntp     UUID:   38.0
                            Username:      abrt     UUID:  173.0

                    -   :代表左对齐
                            如:
                            ]# awk  -F: '{printf "Username: %-10sUUID: %5.1f\n",$1,$3}' /etc/passwd
                            Username: ntp       UUID:  38.0
                            Username: abrt      UUID: 173.0

                    +   :显示数值的正负符号


        4. 操作符

            算术操作符:
                x+y,x-y,x*y,x/y,x^y,x%y :
                -x :单目操作符,变为负数
                +x :转换为数值

            字符串操作符:没有符号的操作符表示字符串连接

            赋值操作符:
                =,+=,-=,*=,/=,^=,%=
                ++,-- :自加,自减

            比较操作符:
                >,>=,<,<=,!=,==

            模式匹配符:
                ~ :匹配
                !~ :是否不匹配

            逻辑操作符:
                && 
                ||
                !  

            函数调用:
                function_name(arg1,arg2,...)

            条件表达式:
                selector?if-true-expression:if-false-expression
                    两个expression间用冒号:分隔

                    例如:]# awk -F':' '{$3>499?usertype="common user":usertype="sys user";printf "%-10s %5d %s\n",$1,$3,usertype}' /etc/passwd


        5. pattern

            (1) empty :空模式,匹配每一行
            (2) /regular expression/ :仅对能被此处模式匹配到的行
                    如:]# awk '/nologin$/{print NR,$0}' /etc/passwd
                        2 bin:x:1:1:bin:/bin:/sbin/nologin
                        3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
                    【注意】此处不能print $1 。

            (3) relational expression :关系表达式,结果为布尔型值,即真和假;结果为真才能被匹配处理;
                真:结果为非0值,非空字符串
                假:结果为0,空字符串
                    例1:
                        ]# awk -F: '$3>499{printf "username:%-10s  UID:%3d\n",$1,$3}' /etc/passwd
                        username:achuDk      UID:500
                        username:gentoo      UID:501
                    例2:
                        ]# awk -F: '$NF~/bash$/{printf "linenum:%-3d username:%-6s bash:%d\n",NR,$1,$NF}' /etc/passwd
                        linenum:1   username:root   bash:0
                        linenum:20  username:achuDk bash:0

            (4) line ranges :行范围
                startline,endline : /pat1/,/pat2/
                    【注意】不支持直接给出数字的格式
                    例如:
                    ]# awk -F: '/^r/,/^h/{SUM=$3+$4;printf "Line record: %-2d  Uname: %10s  UID: %3d  GID: %3d  $3+$4: %3d\n",NR,$1,$3,$4,SUM}' /etc/passwd
                    Line record: 4   Uname:        adm  UID:   3  GID:   4  $3+$4:   7
                    Line record: 5   Uname:         lp  UID:   4  GID:   7  $3+$4:  11
                    例如:
                    ]# awk -F: 'NR>=3&&NR<=10{print}' /etc/passwd
                    daemon:x:2:2:daemon:/sbin:/sbin/nologin
                    adm:x:3:4:adm:/var/adm:/sbin/nologin


            (5) BEGIN/END 模式:
                BEGIN{} :仅在开始处理文件中的文本之前执行一次,如:输出表头
                END{}   :仅在文本处理完成之后,命令结束之前执行一次;


            (6) 常用的action

                1) Expression
                2) Control statements : 控制语句:if,while等;
                3) Compound statements : 组合语句;
                4) input statements :输入语句
                5) output statements :输出语句

            (7) Control statements 控制语句

                if(condition) {statements}
                if(condition) {statements} else {statements}
                while(condition) {statements}
                do {statements} while(condition) 
                for(expr1;expr2;expr3) {statements}
                break
                continue
                delete array[index]
                delete array
                exit
                { statements }

                7.1 if-else

                    使用场景:对awk取得的整行或某个字段做条件判断;
                    语法:
                          单分支:'{if(condition) statement}'
                          多分支:'{if(condition) {statement} else {statement}}'

                        例1:找出/etc/passwd目录下UID<=100的用户打印Uname和UID:

                            单分支语句示例:
                            ]# awk -F: '{if($3<=10)print $1,$3}' /etc/passwd

                            多分支语句示例:
                            例1:]# awk -F: '{if($3<=499){printf "Super user: %s\n",$1}else{printf "Common user: %s\n",$1}}' /etc/passwd
                            例2:]# awk -F: '{if($NF=="/bin/bash") {print NR,$1}else {print $1,$NF}}' /etc/passwd

                            如:显示磁盘空间利用率大于2%的磁盘
                            ]# df | awk '/^\/dev/{print $1,$6}' | awk -F% '{print $1}' | awk '{if($2>=2) printf "The used-percent of this partition has over %%2:%s \n",$1}'
                            The used-percent of this partition has over %2:/dev/sda2 
                            The used-percent of this partition has over %2:/dev/sda1


                7.2 while 循环
                    语法:while(conditiont) statement
                        条件为“真”,进入循环;条件为“假”,退出循环;

                    使用场景:对【一行内的多个字段】或对【数组中的各元素】逐一进行类似处理时使用,因为awk已经对整个文件的所有行进行循环;    

                        示例:显示某文件中所有符合条件的行,对行内的每一个字段,显示字段本身和字段内字符的个数:
                            lenth(WORDS_NAME) :长度函数,显示某字段内字符的个数

                        结果:]# awk '/^[[:space:]]+kernel/{i=1;while(i<=NF) {print $i,length($i);i++}}' /etc/grub.conf 
                        kernel 6
                        /vmlinuz-2.6.32-642.el6.x86_64 30
                        ro 2
                        root=UUID=aadac335-a5b8-40ef-bdbe-ecb0fcc09d01 46
                        rd_NO_LUKS 10
                        rd_NO_LVM 9
                        LANG=en_US.UTF-8 16
                        rd_NO_MD 8
                        SYSFONT=latarcyrheb-sun16 25
                        crashkernel=auto 16
                        KEYBOARDTYPE=pc 15
                        KEYTABLE=us 11
                        rd_NO_DM 8

                        扩展条件:设定条件:仅显示length($i)>=6的字段
                        ]# awk '/^[[:space:]]+kernel/{i=1;while(i<=NF) {if(length($i)>=6) {print $i,length($i)};i++}}' /etc/grub.conf 
                        kernel 6
                        /vmlinuz-2.6.32-642.el6.x86_64 30

                7.3 do-while循环
                    语法:do statemnet while(condition)
                        意义:至少执行一次循环体,即使condition为假

                7.4 for循环
                    语法:for(expr1;expr2;expr3) statement
                                expr1 :控制变量初始化
                                expr2 :条件判断
                                expr3 :控制变量修正表达式
                                for-body :循环体
                        for(variable assignment;condition;iteration process) {for-body}

                        示例:显示某文件中所有符合条件的行,对行内的每一个字段,显示字段本身和字段内字符的个数:使用length()函数。

                        结果:]# awk '/^[[:space:]]+kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub.conf

                    特殊用法:
                        能够遍历数组中的元素:
                            语法:for(var in array) {for-body}

                7.5 switch语句 类似于bash中的case语句
                    语法:swtich(expression) {case VALUE1 or /REGEXP1/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}

                7.6 break和continue 仅针对某一行内多个字段间的循环进行处理
                    break [n] :跳出第n层循环
                    continue  :提前结束本轮循环

                7.7 next 

                    提前结束对本行的处理,直接进入下一行的处理

                        示例:跳过UID号为奇数的行,仅显示UID号为偶数的用户

                        结果:]# awk -F: '{if($3%2!=0) {next} else {print $1,$3}}' /etc/passwd
                            root 0
                            daemon 2


            8. array 数组

                关联数组 :array[index-expression]

                        index-expression 类型
                            (1) 可使用任意字符串:
                            (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
                                【注意】
                                    1、可使用任意字符串,字符串要使用双引号;
                                    2、如果想判断数组中是否存在某元素或某元素是否为空时,要使用“index in array”格式进行,千万不要通过引用这个元素来判断

                                weekdays["mon"]="Monday"
                                例如:
                                ]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"],weekdays["tue"]}'
                                Monday Tuesday

                        要遍历数组中的每个元素,要使用for循环;
                            for(var in array) {for-body}

                            例1:
                            ]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
                            Monday
                            Tuesday

                            【注意】var会遍历array的每个索引;

                            例2:统计tcp协议的所有端口的连接状态:
                                ]# netstat -tnl | awk '{print $4,$0}' | awk '/^[[:digit:]]+/{state[$NF]++}END{for(i in state) {print i,state[i]}}'
                                LISTEN 3

                            例3:统计所有进程中以root身份运行的进程
                                ]# ps aux | awk '{user[$1]++}END{for(i in user);{print i,user[i]}}'
                                root 141

                            例4:统计/etc/fstab中所有fs出现的频率分布
                                ]# cat /etc/fstab | awk '/^[[:alnum:]]/{fstype[$3]++}END{for(i in fstype) {printf "fs-type: %-10s  distribution: %d \n",i,fstype[i]}}'
                                fs-type: devpts      distribution: 1 
                                fs-type: swap        distribution: 1 
                                fs-type: sysfs       distribution: 1 
                                fs-type: proc        distribution: 1 
                                fs-type: tmpfs       distribution: 1 
                                fs-type: ext4        distribution: 4

* 例5:统计文件中每个单词出现的次数:
]# awk -F: ‘{for(i=1;i<=NF;i++){words[$i]++}}END{for(i in words) {print i,words[i]}}’ /etc/passwd | sort -k 2 -nr

                                ]# awk '{for(i=1;i<=NF;i++){fstype[$i]++}}END{for(i in fstype) {print i,fstype[i]}}' /etc/fstab


            9. 函数

                9.1 内置函数
                    rand() :返回0和1之间的随机数
                        如:]# awk 'BEGIN{print rand()}'
                            0.237788
                        【注意】只有第一次取是随机的,以后都会成为定值

                    字符串处理:
                        length([s]) :返回指定字符串的长度
                        sub(r,s,[t]) :以r表示的模式来查找t所表示的字符串中的匹配的内容,并将其第一次出现替 换为s所表示的内容;t可以省略
                        gsub(r,s,[t]) :全局替换

                    split(s,a[,r]) :以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;r可以省略
                        例如:统计netstat信息中的local address 去除端口号的数据:
                            ]# netstat -tnl | awk '/^tcp/{split($4,ip,":");count[ip[1]]++}END{for(i in count) {print i,count[i]}}'
                             3
                            127.0.0.1 1
                            0.0.0.0 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。 最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。它的设计思想来源于 SNOBOL4 、sed 、Marc Rochkind设计的有效性语言、语言工具 yacc 和 lex ,当然还从 C 语言中获取了一些优秀的思想。在最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。 尽管操作可能会很复杂,但命令的语法始终是: awk '{pattern + action}' 或者 awk 'pattern {action}' 其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 gawkAWKGNU 版本。 一般的UNIX作业系统,本身即附有AWK,不同的UNIX作业系统所附的AWK其版本亦不尽相同,若读者所使用的系统上未附有AWK,可通过 anonymous ftp 到下列地方取得: phi./pub/gnu ftp/UNIX/gnu preppub/gnu 注 解:一种编程语言,因其模式匹配语法而特别有用,通常用于数据检索和数据转换。一个GNU版本称为Gawk

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值