简介
awk 是一个强大的文本分析工具, 相对于 grep 的查找, sed 的编辑, awk 在其对数据分析并生成报告时, 显得尤为强大. 简单来说 awk 就是把文件逐行的读入, 以空格为默认分隔符将每行切片, 切开的部分再进行各种分析处理.
awk 有 3 个不同版本: awk,nawk 和 gawk, 未作特别说明, 一般指 gawk,gawk 是 AWK 的 GNU 版本.
awk 其名称得自于它的创始人 Alfred Aho ,Peter Weinberger 和 Brian Kernighan 姓氏的首个字母. 实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为 "样式扫描和处理语言". 它允许您创建简短的程序, 这些程序读取输入文件, 为数据排序, 处理数据, 对输入执行计算以及生成报表, 还有无数其他的功能.
使用方法
awk '{pattern + action}' {filenames}
尽管操作可能会很复杂, 但语法总是这样, 其中 pattern 表示 AWK 在数据中查找的内容, 而 action 是在找到匹配内容时所执行的一系列命令. 花括号 ({}) 不需要在程序中始终出现, 但它们用于根据特定的模式对一系列指令进行分组. pattern 就是要表示的正则表达式, 用斜杠括起来.
awk 语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息, awk 抽取信息后, 才能进行其他文本操作. 完整的 awk 脚本通常用来格式化文本文件中的信息.
通常, awk 是以文件的一行为处理单位的. awk 每接收文件的一行, 然后执行相应的命令, 来处理文本.
调用 awk
有三种方式调用 awk
1. 命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中, commands 是真正 awk 命令,[-F 域分隔符]是可选的. input-file(s) 是待处理的文件.
在 awk 中, 文件的每一行中, 由域分隔符分开的每一项称为一个域. 通常, 在不指名 - F 域分隔符的情况下, 默认的域分隔符是空格.
2.shell 脚本方式
将所有的 awk 命令插入一个文件, 并使 awk 程序可执行, 然后 awk 命令解释器作为脚本的首行, 一遍通过键入脚本名称来调用.
相当于 shell 脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3. 将所有的 awk 命令插入一个单独文件, 然后调用:
awk -f awk-script-file input-file(s)
其中,-f 选项加载 awk-script-file 中的 awk 脚本, input-file(s)跟上面的是一样的.
本章重点介绍命令行方式.
入门实例
假设 last -n 5 的输出如下
- [root@www ~]# last -n 5 <== 仅取出前五行
- root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in
- root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
- root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
- dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
- root tty1 Fri Sep 5 14:09 - 14:10 (00:01)
如果只是显示最近登录的 5 个帐号
- #last -n 5 | awk '{print $1}'
- root
- root
- root
- dmtsai
- root
awk 工作流程是这样的: 读入有'\n'换行符分割的一条记录, 然后将记录按指定的域分隔符划分域, 填充域,$0 则表示所有域,$1 表示第一个域,$n 表示第 n 个域. 默认域分隔符是 "空白键" 或 "[tab]键", 所以 $1 表示登录用户,$3 表示登录用户 ip, 以此类推.
如果只是显示 / etc/passwd 的账户
- #cat /etc/passwd |awk -F ':' '{print $1}'
- root
- daemon
- bin
- sys
这种是 awk+action 的示例, 每行都会执行 action{print $1}.
-F 指定域分隔符为':'.
如果只是显示 / etc/passwd 的账户和账户对应的 shell, 而账户与 shell 之间以 tab 键分割
- #cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'
- root /bin/bash
- daemon /bin/sh
- bin /bin/sh
- sys /bin/sh
如果只是显示 / etc/passwd 的账户和账户对应的 shell, 而账户与 shell 之间以逗号分割, 而且在所有行添加列名 name,shell, 在最后一行添加 "blue,/bin/nosh".
- cat /etc/passwd |awk -F ':' 'BEGIN {print"name,shell"} {print $1","$7} END {print"blue,/bin/nosh"}'
- name,shell
- root,/bin/bash
- daemon,/bin/sh
- bin,/bin/sh
- sys,/bin/sh
- ....
- blue,/bin/nosh
awk 工作流程是这样的: 先执行 BEGING, 然后读取文件, 读入有 / n 换行符分割的一条记录, 然后将记录按指定的域分隔符划分域, 填充域,$0 则表示所有域,$1 表示第一个域,$n 表示第 n 个域, 随后开始执行模式所对应的动作 action. 接着开始读入第二条记录...... 直到所有的记录都读完, 最后执行 END 操作.
搜索 / etc/passwd 有 root 关键字的所有行
- #awk -F: '/root/' /etc/passwd
- root:x:0:0:root:/root:/bin/bash
这种是 pattern 的使用示例, 匹配了 pattern(这里是 root)的行才会执行 action(没有指定 action, 默认输出每行的内容).
搜索支持正则, 例如找 root 开头的: awk -F: '/^root/' /etc/passwd
搜索 / etc/passwd 有 root 关键字的所有行, 并显示对应的 shell
- # awk -F: '/root/{print $7}' /etc/passwd
- /bin/bash
这里指定了 action{print $7}
- #awk -F ':' '{print"filename:"FILENAME",linenumber:"NR",columns:"NF",linecontent:"$0}' /etc/passwd
- filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
- filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
- filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
- filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
- awk '{count++;print $0;} END{print"user count is ", count}' /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- ......
- user count is 40
- awk 'BEGIN {count=0;print"[start]user count is ", count} {count=count+1;print $0;} END{print"[end]user count is ", count}' /etc/passwd
- [start]user count is 0
- root:x:0:0:root:/root:/bin/bash
- ...
- [end]user count is 40
- ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print"[end]size is ", size}'
- [end]size is 8657198
- ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print"[end]size is ", size/1024/1024,"M"}'
- [end]size is 8.25889 M
- if (expression) {
- statement;
- statement;
- ... ...
- }
- if (expression) {
- statement;
- } else {
- statement2;
- }
- if (expression) {
- statement1;
- } else if (expression1) {
- statement2;
- } else {
- statement3;
- }
- ls -l |awk 'BEGIN {size=0;print"[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print"[end]size is ", size/1024/1024,"M"}'
- [end]size is 8.22339 M
- awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
- 0 root
- 1 daemon
- 2 bin
- 3 sys
- 4 sync
- 5 games
- ......
来源: http://www.bubuko.com/infodetail-2769638.html