1、简介
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具(行编译器)。
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
2、awk基础介绍
2.1 awk两种语法
// 语法
awk [options] 'command' {file_name}
2.2 常用参数
参数 | 注释 |
---|---|
-F fs | 指定输入文件拆分隔符,fs是一个字符串或者是一个正侧表达式,如-F |
-v | 赋值一个用户定义变量 |
-f | 从脚本中读取awk命令 |
-W | 在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。 |
’ ’ | 引用代码块 |
// | 匹配代码块,可以是字符串或正则表达式 |
{} | 命令代码块,包含一条或多条命令 |
; | 多条命令使用分号分隔 |
BEGIN | 在 awk 程序一开始,未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次 |
END | 在 awk 程序处理完所有数据,即将结束时执行?END 后的动作只在程序结束时执行一次 |
2.3 常用内置变量
参数 | 注释 |
---|---|
$0 | 表示整个当前行 |
$1 ~ $n | 当前记录的第N个字段 |
FS | 输入字段分隔符 |
RS | 输入记录分割符,默认换行符 |
NF | 字段个数就是列 |
NR | 记录数,就是行号,默认从1开始 |
FNR | 与NR类似,不过多文件记录不递增,每个文件都从1开始 |
OFS | 输出字段分隔符,默认空格 |
ORS | 输出记录分割符,默认换行符 |
\n | 换行符 |
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
= += -= *= /= %= ^= **= | 赋值 |
&& | 逻辑与 |
< <= > >= != == | 关系运算符 |
* / % | 乘、除、求余 |
$ | 字段引用 |
3、awk操作举例
3.1 简单操作
打印列的内容
print $n :对应着列
[root@centos1 ~]# cat test1
hello tom
hello jerry
hello zhangsan
hello lisi
[root@centos1 ~]# awk '{print $1}' test1
hello
hello
hello
hello
[root@centos1 ~]# awk '{print $2}' test1
tom
jerry
zhangsan
lisi
打印行的内容
NR==number
[root@centos1 ~]# cat test1
hello tom
hello jerry
hello zhangsan
hello lisi
[root@centos1 ~]# awk 'NR==1' test1
hello tom
[root@centos1 ~]# awk 'NR==3' test1
hello zhangsan
打印行切列的内容
[root@centos1 ~]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 876M 0 876M 0% /dev
tmpfs 895M 0 895M 0% /dev/shm
tmpfs 895M 8.7M 887M 1% /run
tmpfs 895M 0 895M 0% /sys/fs/cgroup
/dev/mapper/cs-root 17G 7.9G 9.2G 47% /
/dev/sda1 1014M 195M 820M 20% /boot
tmpfs 179M 0 179M 0% /run/user/0
[root@centos1 ~]# df -h |awk 'NR==2{print $2}'
876M
输出文本内容
\n:转换
\t:tab键
[root@centos1 ~]# echo |awk 'BEGIN{print "name""\t""age""\n""tom""\t""15""\n""rhce""\t""20"}'
name age
tom 15
rhce 20
测试整数字母空格
[root@centos1 ~]# cat test2
/[0-9]+/{print "这是一个数字"}
/[a-zA-Z]+/{print "这个是一个字母"}
/^$/{print "这是一个空格"}
[root@centos1 ~]# awk -f test2
9
这是一个数字
s
这个是一个字母
这是一个空格
3.2 awk脚本格式
[root@centos1 ~]# cat test
香飘飘 2
优乐美 3
阿萨姆 4
咖啡 5
[root@apache ~]# cat test.sh
#!/bin/bash
echo "商品列表:"
awk '{print NR ".",$1,$2"元"}' test
read -p "请输入要买的商品编号:" choice
read -p "请输入购买个数:" num
awk -vcount=$num -vline=$choice 'NR==line{print "您购买了"count"杯"$1,"共消费"$2*count"元" }' list
[root@centos1 ~]# /bin/bash test.sh
商品列表:
1. 香飘飘 2元
2. 优乐美 3元
3. 阿萨姆 4元
4. 咖啡 5元
请输入要买的商品编号:2
请输入购买个数:2
您购买了2杯优乐美 共消费4元
3.3 awk运算
[root@centos1 ~]# echo "a b c d"|awk 'BEGIN{one=0;two=4}{print $(one+two)}'
d #a对应$1,d对应$4
[root@centos1 ~]# echo |awk 'BEGIN{print 0.2/10}'
0.02
3.4 awk取主机ip地址
[root@centos1 ~]# ip a |grep 'inet '|grep -v '127.0.0.1'|awk -F'[ /]+' '{print $3}'
192.168.91.134
3.5 awk匹配练习
// test3文本内容
[root@centos1 ~]# cat test3
607-624-0000
(607) 624-0000
(607)624-0000
1-607-624-0000
1 607-624-0000
1(607)624-0000
// 打印607-624-0000
[root@centos1 ~]# awk '/^6[0-9]+-[0-9]+/' test3
607-624-0000
// 匹配俩行(607)的内容
[root@centos1 ~]# awk '/^\([0-9]+\)/' test3
(607) 624-0000
(607)624-0000
3.6 -v传递变量参数
[root@centos1 ~]# cat test4
1 This is html
3 How are you
5 You are beautiful
7 happy mid-Autumn Festival
[root@centos1 ~]# awk -v a=1 '{print $1,$1+a}' test4
1 2
3 4
5 6
7 8
3.7 -F使用分隔符查看文件信息
原文件
[root@centos1 ~]# cat test4
1 This is html
3 How are you
5 You are beautiful
7 happy mid-Autumn Festival
输出文本中每行的第一列和第四列的字符
[root@centos1 ~]# awk '{print $1,$4}' test4
1 html
3 you
5 beautiful
7 Festival
awk -F #-F相当于内置变量FS, 指定分割字符
使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割
[root@centos1 ~]# awk -F '[ ,]' '{print $1,$2,$4}' test4
1 This html
3 How you
5 You beautiful
7 happy Festival
3.8 逻辑运算
// 原文件
[root@centos1 ~]# cat test4
1 This is html
3 How are you
5 You are beautiful
7 happy mid-Autumn Festival
过滤第一列大于 2 的行
[root@centos1 ~]# awk '$1>2' test4
3 You are beautiful
5 You are beautiful
7 happy mid-Autumn Festival
过滤第一列等于 3 的行,并输出第一列和第三列
[root@centos1 ~]# awk '$1==3 {print $1,$3}' test4
3 are
过滤第一列大于 1 并且第三列等于 ’are’ 的行
[root@centos1 ~]# awk '$1>1 && $3=="are" {print $1,$2,$3}' test4
3 How are
5 You are
模式取反
取第三行,不包含is 行的第二列和第四列输出
[root@centos1 ~]# awk '$3 !~ /is/ {print $2,$4}' test4
How you
You beautiful
happy Festival
3.9 BEGIN与END关键字
BEGIN 会强制 awk 在读取数据前执行该关键字后指定的脚本命令
// 原文件test5
[root@centos1 ~]# cat test5
how
are
yoe
gf
// 使用BEGIN命令,增加第0行内容“cc dd”
[root@centos1 ~]# awk 'BEGIN {print "cc dd"} {print $0}' test5
cc dd
how
are
yoe
gf
END关键字和 BEGIN 关键字相对应,END 关键字允许我们指定一些脚本命令,awk 会在读完数据后执行它们
// 原文件test5
[root@centos1 ~]# cat test5
how
are
yoe
gf
[root@centos1 ~]# awk 'BEGIN {print "cc dd"} {print $0} END {print"byebye"}' test5
cc dd
how
are
yoe
gf
byebye
3.10 RS与OFS
RS:输入的记录分隔符
// 原文件test6
[root@centos1 ~]# cat test6
lisi 80 90 50 45
zhangsan 97 98 95 65 30
wangwu 40 52 50 50 60 82
以换行符作为字段分隔符,将记录分割符设置为空,来出输出第一列的内容
[root@centos1 ~]# awk 'BEGIN{FS="\n";RS=""}{print $1}' test6
lisi 80 90 50 45
这样设置后,程序就会把它认为是一个整体。
OFS:输出字段分隔符
OFS是和FS等效的输出分隔符,他的默认值为空格
// 原文件test6
[root@centos1 ~]# cat test6
lisi 80 90 50 45
zhangsan 97 98 95 65 30
wangwu 40 52 50 50 60 82
以换行符作为字段分隔符,将记录分割符设置为空,将输出分隔符改为冒号来出输出第一列的内容。
[root@centos1 ~]# awk 'BEGIN{FS="\n";RS="";ORS=":"}{print $1}' test6
lisi 80 90 50 45:zhangsan 97 98 95 65 30:wangwu 40 52 50 50 60 82: