概述
awk是一个功能非常强大的的数据操作实用程序。作为一个程序,awk可以对大范围的数据进行匹配搜索和修改,同时它还具有一些其他编程语言类似的特征。实用程序awk与grep相同,都是一个模式匹配工具。除此之外,它还拥有以下功能:当找到某模式的匹配项后,对该匹配项,进行特定的复杂操作。另外,与其他编程语言一样,在awk中,可以使用循环,条件语句以及变量。
1. 使用awk选择记录:
下面我们就进入awk的用法测试。
测试文件内容如下:
例子1:
[root@VM_89_124_centos awk]# awk '/Fish/{print}' test.txt
Fish Meat 3.79 3 n
分析:
- awk :指示shell运行实用程序awk
- ' ' : 指示shell不解释单引号之间的数据,以确保awk收到的信息未被更改。
- /Fish/ : 一对斜线指明了匹配模式,即选择特定数据库中记录的一个标准。所有含有目标行的都会被匹配,并运行其后的操作。
- {print} : 大括号间的print命令动作语句指示awk输出选定的记录。语句print是awk中的众多动作之一。除非另有指示,否则print命令将输出含有目标的全部记录。
- test.txt : 输入文件名。awk读取该文件,并将指定的模式-动作语句应用于该数据库中的每行。
上面图文并茂的解释了awk命令的执行流程。下面用更多的例子来加深理解。
更多的例子说明
- 不指定动作
[root@VM_89_124_centos awk]# awk '/Meat/' test.txt
Chichen Meat 4.89 2 n
Fish Meat 3.79 3 n
awk的默认动作是使用print命令输出符合标准要求的全部记录。
- 不指定模式
[root@VM_89_124_centos awk]# awk '{print}' test.txt
Carrots veg 1.39 1 n
Milk Dairy 1.89 2 n
Magazine Sundry 3.50 2 n
Cheese Dairy 4.39 1 n
Sandwich Deli 3.89 2 y
Onions Veg .89 6 n
Chichen Meat 4.89 2 n
Newspaper Sundry 1.00 1 y
Fish Meat 3.79 3 n
Floorwax Hshld 4.65 1 y
Melon Fruit 1.98 3 n
Celery Veg 1.79 1 n
Napkins Hshld 1.49 6 y
如果没有指定模式(目标),awk认为数据库中的所有记录都是匹配项,并且对所有记录(行)运行awk语句中的指定动作。
2.使用awk操作数据库
2.1 输出数据库中的一个字段元素
[root@VM_89_124_centos awk]# awk '{print $1}' test.txt
Carrots
Milk
Magazine
Cheese
Sandwich
Onions
Chichen
Newspaper
Fish
Floorwax
Melon
Celery
Napkins
2.2 使用awk的预定义变量
上列中,变量$1指示awk仅显示数据库test.txt中所有记录的第一个字段。对awk来说,变量$1指各记录第一个字段的值。
变量(variable)是一个具有变量名和变量值的表达式。在书写awk脚本时,变量通常由用户或程序员定义。此外,awk程序代码中还有一些类似$1的预定义变量。在awk程序代码中,经常可以看到由一个美元符号$和一个数字组成的字段变量。符号$是字段操作符(field operator),1代表着相应的字段序号(literal number component)。上例中,变量$1指的就是数据库中各记录第一个字段的值。通常,各个记录或数据库的第一个字段值都不相同。但是,对awk来说,当前检查的记录的第一个字段值就是$1的值,因为这种变量关系是awk已经预先定义的。
2.3 显示多个字段
[root@VM_89_124_centos awk]# awk '{print $1 $3 $2}' test.txt
Carrots1.39veg
Milk1.89Dairy
Magazine3.50Sundry
Cheese4.39Dairy
Sandwich3.89Deli
Onions.89Veg
Chichen4.89Meat
Newspaper1.00Sundry
Fish3.79Meat
Floorwax4.65Hshld
Melon1.98Fruit
Celery1.79Veg
Napkins1.49Hshld
可以看到,在输出目标时我可以指定输出的顺序。但是输出中各记录的所有字段挤在一起。字段之间没有空格是因为没有使用指令告诉awk字段之间放置空格。
2.4 在awk输出的结果中插入空格
为了让输出结果有更好的可读性,必须要求awk在输出各字段时,将各字段分隔开。
[root@VM_89_124_centos awk]# awk '{print $1,$3,$2}' test.txt
Carrots 1.39 veg
Milk 1.89 Dairy
Magazine 3.50 Sundry
Cheese 4.39 Dairy
Sandwich 3.89 Deli
Onions .89 Veg
Chichen 4.89 Meat
Newspaper 1.00 Sundry
Fish 3.79 Meat
Floorwax 4.65 Hshld
Melon 1.98 Fruit
Celery 1.79 Veg
Napkins 1.49 Hshld
可以看出就是多加了逗号","用以将字段隔开,用空格。也可以使用"\t"来讲字段隔开,用tab键。
[root@VM_89_124_centos awk]# awk '{print $1"\t"$3"\t"$2}' test.txt
Carrots 1.39 veg
Milk 1.89 Dairy
Magazine 3.50 Sundry
Cheese 4.39 Dairy
Sandwich 3.89 Deli
Onions .89 Veg
Chichen 4.89 Meat
Newspaper 1.00 Sundry
Fish 3.79 Meat
Floorwax 4.65 Hshld
Melon 1.98 Fruit
Celery 1.79 Veg
Napkins 1.49 Hshld
2.5 选择所有字段
[root@VM_89_124_centos awk]# awk '{print $0}' test.txt
Carrots veg 1.39 1 n
Milk Dairy 1.89 2 n
Magazine Sundry 3.50 2 n
Cheese Dairy 4.39 1 n
Sandwich Deli 3.89 2 y
Onions Veg .89 6 n
Chichen Meat 4.89 2 n
Newspaper Sundry 1.00 1 y
Fish Meat 3.79 3 n
Floorwax Hshld 4.65 1 y
Melon Fruit 1.98 3 n
Celery Veg 1.79 1 n
Napkins Hshld 1.49 6 y
预定义变量$0是指记录中的所有字段,即整个行。全字段变量$0用于定义或匹配一条完整记录的属性。输出了所有记录的全部字段。这个和之前的awk '{print}' test.txt
是一样的效果。
2.6识别变量和字符串
$1是一个变量。awk把每个变量都看成一个指令,用变量的值替换该变量本身。用户可以创建变量,并使用awk来操作。
(1)输入:
awk -v item='Grocery Item' '{print item,$1}' test.txt
[root@VM_89_124_centos awk]# awk -v item='Grocery Item' '{print item,$1}' test.txt
Grocery Item Carrots
Grocery Item Milk
Grocery Item Magazine
Grocery Item Cheese
Grocery Item Sandwich
Grocery Item Onions
Grocery Item Chichen
Grocery Item Newspaper
Grocery Item Fish
Grocery Item Floorwax
Grocery Item Melon
Grocery Item Celery
Grocery Item Napkins
-v :传给awk的第一个参数,指示awk在该参数之后,将定义一个变量。
(2)还可以告诉awk,对象可以是一个没有特殊含义的字符串,输入:
awk '{print "item:", $1, "Price:", $3}' test.txt
[root@VM_89_124_centos awk]# awk '{print "item:", $1, "Price:", $3}' test.txt
item: Carrots Price: 1.39
item: Milk Price: 1.89
item: Magazine Price: 3.50
item: Cheese Price: 4.39
item: Sandwich Price: 3.89
item: Onions Price: .89
item: Chichen Price: 4.89
item: Newspaper Price: 1.00
item: Fish Price: 3.79
item: Floorwax Price: 4.65
item: Melon Price: 1.98
item: Celery Price: 1.79
item: Napkins Price: 1.49
双引号里面的字母字符仅仅是一些字符,没有特别的含义。如果是数字的话则无需加上双引号。
[root@VM_89_124_centos awk]# awk '{print 111, $1, 222, $3}' test.txt
111 Carrots 222 1.39
111 Milk 222 1.89
111 Magazine 222 3.50
111 Cheese 222 4.39
111 Sandwich 222 3.89
111 Onions 222 .89
111 Chichen 222 4.89
111 Newspaper 222 1.00
111 Fish 222 3.79
111 Floorwax 222 4.65
111 Melon 222 1.98
111 Celery 222 1.79
111 Napkins 222 1.49
对比一下:
[root@VM_89_124_centos awk]# awk '{print "111:", $1, "222:", $3}' test.txt
111: Carrots 222: 1.39
111: Milk 222: 1.89
111: Magazine 222: 3.50
111: Cheese 222: 4.39
111: Sandwich 222: 3.89
111: Onions 222: .89
111: Chichen 222: 4.89
111: Newspaper 222: 1.00
111: Fish 222: 3.79
111: Floorwax 222: 4.65
111: Melon 222: 1.98
111: Celery 222: 1.79
111: Napkins 222: 1.49
2.7使用选项改变字段定界符。
[root@VM_89_124_centos awk]# awk -F: '{print $1,$4,$7}' /etc/passwd|head -5
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
adm 4 /sbin/nologin
lp 7 /sbin/nologin
[root@VM_89_124_centos awk]# awk -F: '{print $1 $4 $7}' /etc/passwd|head -5
root0/bin/bash
bin1/sbin/nologin
daemon2/sbin/nologin
adm4/sbin/nologin
lp7/sbin/nologin
选项-F通知awk,当它读取输入数据时,应当把冒号(:)作为字段定界符(不写的话,默认是以空格为定界符)。但即使改变了输入字段的定界符,输出中的字段定界符依然是空格。对比上面的两种方式可以看出。
同样,如果输入" -F'*' ",awk会把符号*当成字符定界符。
awk可认为是一门编程语言。基础部分比较简单,尝试写这篇文档感觉抓不住要陈述的点,但是梳理一下也是好的,awk的用法也在于平时多积累多尝试。