1. awk简介
awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。
awk处理文本和数据的方式为:它逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行你想要的操作。
- 如果没有指定匹配模式,则所有的行都将被处理;
- 如果没有指定处理动作,则把匹配到的行显示到标准输出(屏幕);
awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展,使用awk --help显示帮助。
2. awk命令格式
awk [options] 'pattern{actions}' file --- 通常有选项、模式、操作三部分组成。
- 选项(options)包括:
- -F 指定域分隔符,比如-F:或者-F'[:,]'等
- -f scriptfile 从脚本中读取awk命令
- -v var=value 给一个用户定义变量赋值
- --help
- --version
- 模式(pattern)可以是以下任意一个:
- /正则表达式/
- 关系表达式 --- 可以是字符串或数字的比较,如$2>$1选择第二个字段比第一个字段大的行。
- 模式匹配表达式 --- 用运算符~(匹配)和~!(不匹配)
- 范围模板 --- 指定行的范围,该语法不能包括BEGIN和END模式
- BEGIN --- 让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
- END --- 让用户在最后一条输入记录被读取之后发生的动作
- 操作(action)是指定的处理动作,由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内;通常情况下为print打印操作。当然也可以有赋值、流控制等操作。
3. 记录和域
- 记录(Record)
- awk把每一个以换行符结束的行称为一个"记录"。
- 记录分隔符:记录默认的输入和输出分隔符都是回车。内建变量RS(Record Separator)保存输入记录分隔符的值,内建变量ORS(Ouptut Record Separator)保存输出记录分隔符的值。
- $0变量:它指的是整条记录。eg: awk '{print $0}' test 将输出test文件中的所有记录。
- 变量NR(Number of Record):一个计数器,每处理完一条记录,NR的值就增加1。eg: awk '{print NR,$0}' test 将输出test文件中所有记录,并在记录前显示记录号。
- 域(Field)
- 记录中每个单词称做"域"。
- 域分隔符:默认情况下以空格或tab分隔,当然可以用选项-F来指定,内建变量FS(Field Separator)保存输入域分隔符的值,内建变量OFS(Output Field Separator)保存输出域分隔符的值,默认是一个空格。如$ awk -F: '{print $1,$5}' test,$1和$5间的逗号就是OFS的值。
- 变量NF(Number of Field):awk可跟踪域的个数,并在内建变量NF中保存该值。同样为一个计数器,针对每条记录(每行),处理完一个字段,NF的值就增加1。每次新行开始的时候NF清0。
当然,我们可以通过如下方式修改输入或输出域分隔符(一般只修改FS或OFS):
a) 通过-F命令行选项和内建变量FS修改输入域分隔符。如下:
1> echo "a:b:c:d" | awk -F: '{print $1,$2,$3,$4}' 将打印以冒号为分隔符的每个域。
2> echo "a:b:c:d" | awk 'BEGIN{FS=":"}{print $1,$2,$3,$4}' 将打印以冒号为分隔符的每个域。
3> awk -F'[:#]' '{print $1,$3}' test 可以同时使用多个域分隔符,这时应把分隔符写在方括号中,表示以空格、问号和井号作为分隔符。
b) 通过OFS内建变量修改输出域分隔符。如下:
1> echo a b c d | awk '{print $1":"$2":"$3":"$4}'
2> echo a b c d | awk '{OFS=":";print $1,$2,$3,$4}'
3> echo a b c d | awk 'BEGIN {OFS=":"}{print $1,$2,$3,$4}'
4. BEGIN模块
5. END模块
6. 几个实例
- awk '/root/' test --- 打印包含模式root的行;
- awk '/^(no|so)/' test --- 打印所有以模式no或so开头的行;
- awk '/^[ns]/{print $1}' test --- 如果记录以n或s开头,就打印这个记录的第一个域;
- awk '/test/{print $1 + 10}' test --- 如果记录包含正则表达式test,则第一个域加10并打印出来;
- awk '$3 < 100' test --- 如果第三个域小于100,则打印这些行;
- awk '$1 + $2 > 100' test --- 如果第一和第二个域相加大于100,则打印这些行;
- awk '$1 > 5 && $2 < 10' test --- 如果第一个域大于5,并且第二个域小于10,则打印这些行;
- awk '{max = {$1 > $3} ? $1: $3: print max}' test --如果第一个域大于第三个域,$1就赋值给max,否则$3就赋值给max
- awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test --- 如果第一个域大于5,则打印问号后面的表达式值,否则打印冒号后面的表达式值;
- awk '$1 == 100 || $2 < 50' test --- 如果第一个域等于100或者第二个域小于50,则打印该行;
- awk '$1 != 10' test --- 如果第一个域不等于10就打印该行;
- awk '/root/,/mysql/' test --- 将显示root第一次出现到mysql第一次出现之间的所有行。范围模板匹配从第一个模板的第一次出现到第二个模板的第一次出现之间所有行。如果有一个模板没出现,则匹配到开头或末尾;
- awk '/^root/,/^mysql/' test --- 打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的以正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾;
- awk '$1 ~/^root/' test --- 将显示test文件第一列中以root开头的行;
- awk '$1 ~/[0-9][0-9]$/(print $1}' test --- 如果第一个域以两个数字结束,就打印这个记录;
7. awk编程
- 变量
- 重定向和管道
- 条件语句
- 循环语句
- 数组
- awk的内建函数
- 字符串函数
- 时间函数
- 数学函数
- 自定义函数
How-to
Table 1: awk的环境变量
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段 |