简介
AWK, 数据过滤工具 (类似于grep,比grep强大),属数据处理引擎,基于模式匹配检查输入文本,逐行处理并输出。通常用在Shell脚本中,获取指定的数据,单独使用时,可对文本数据做统计
创造者:Aho、Weinberger、Kernighan
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程: 依次对每一行进行处理,然后输出
语法格式
格式
格式1:前置命令 | awk [选项] ‘条件{编辑指令}’
格式2:awk [选项] ‘条件{编辑指令}’ 文件…
编辑指令如果包含多条语句时,可以用分号分隔,处理文本时,若未指定分隔符,则默认将空格、制表符等作为分隔符。print是最常见的指令
选项
-F:指定分隔符,可省略(默认空格或Tab位)
-V:调用外部Shell变量 variable
[root@lzx ~]# cat a.sh
#!/bin/bash
# 提取密码,awk通过-v调用i变量
user="root shsnc"
for i in $user
do
awk -F: -v X=$i '$1==X{print X "---" $2}' /etc/soft
done
[root@lzx ~]# bash a.sh
root---$1$jnKwNDZu$VsBXP9FMOGDVQ6./lpJ851
shsnc---$6$NVUFK2rh$IcLw9/6ioKY5TO5dj3heiy3R1pUnh/lYkKYBMnn6rmw4QsKSHTiEWxQlKaT2EZaMVrugXVVpWN6quDkMoPcSg1
awk的内置变量
变量 | 功能 | 案例 |
---|---|---|
FS | 保存或设置字段分隔符,如FS=”:” | |
$n | 指定分隔的第n个字段,如$1、$3分别表示第1、第3列 | awk -F: ‘{print “用户名:”$1}’ /etc/passwdawk -F “:” ‘{print “第2列是:”,$2}’ a.txt输出第1、7个字段# awk -F: ‘{print $1","$7}’ a.txt # awk -F “:” ‘{print $1","$7}’ a.txt |
$0 | 当前读入的整行文本内容 | |
NF | 记录当前处理行的字段个数(列数) | 输出最后一列KaTeX parse error: Expected '}', got 'EOF' at end of input: …'{print “Last:”NF}’ a.txt |
NR | 记录当前已读入行的数量(行数) | awk ‘{print NR}’ a.txt |
FNR | 当前行在源文件中的行号 | awk ‘{print “第”FNR”行”,“有“NF”列”}’ a.txt b.txt |
-f指定脚本文件
awk -f script.awk file
BEGIN{
FS=":"
}
{print $1} //效果与awk -F":" '{print $1}'相同,只是分隔符使用FS在代码自身中指定
awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test
I find 4 blank lines.
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}' //计算文件大小
total size is 17487
-F指定分隔符
$1 指指定分隔符后,第一个字段,$3第三个字段, \t是制表符
一个或多个连续的空格或制表符看做一个定界符,即多个空格看做一个空格
awk -F":" ‘{print $1}’ /etc/passwd | |
awk -F":" ‘{print $1 $3}’ /etc/passwd | $1与$3相连输出,不分隔 |
awk -F":" ‘{print $1,$3}’ /etc/passwd | 多了一个逗号,$1与$3使用空格分隔 |
awk -F":" ‘{print $1 " " $3}’ /etc/passwd | $1与$3之间手动添加空格分隔 |
awk -F":" ‘{print “Username:” $1 “\t\t Uid:” $3 }’ /etc/passwd | 自定义输出 |
awk -F: ‘{print NF}’ /etc/passwd | 显示每行有多少字段 |
awk -F: ‘{print $NF}’ /etc/passwd | 将每行第NF个字段的值打印出来 |
awk -F: ‘NF==4 {print }’ /etc/passwd | 显示只有4个字段的行 |
awk -F: ‘NF>2{print $0}’ /etc/passwd | 显示每行字段数量大于2的行 |
awk ‘{print NR,$0}’ /etc/passwd | 输出每行的行号 |
awk -F: ‘{print NR,NF,$NF,"\t",$0}’ /etc/passwd | 依次打印行号,字段数,最后字段值,制表符,每行内容 |
awk -F: ‘NR==5{print}’ /etc/passwd | 显示第5行 |
awk -F: 'NR==5 | |
route -n | awk ‘NR!=1{print}’ |
IF语句
必须用在{}中,且比较内容用()扩起来
awk -F: ‘{if($1~/mail/) print $1}’ /etc/passwd
awk -F: ‘{if($1~/mail/) {print $1}}’ /etc/passwd
awk -F: ‘{if($1~/mail/) {print $1} else {print $2}}’ /etc/passwd
条件表达式
== != > >=
awk -F":" ‘$1==“mysql”{print $3}’ /etc/passwd | |
awk -F":" ‘{if($1==“mysql”) print $3}’ /etc/passwd | 与上面相同 |
awk -F":" ‘$1!=“mysql”{print $3}’ /etc/passwd | 不等于 |
awk -F":" ‘$3>1000{print $3}’ /etc/passwd | 大于 |
awk -F":" ‘$3>=100{print $3}’ /etc/passwd | 大于等于 |
awk -F":" ‘$3<1{print $3}’ /etc/passwd | 小于 |
awk -F":" ‘$3<=1{print $3}’ /etc/passwd | 小于等于 |
逻辑运算符
&& ||
awk -F: ‘$1~/mail/ && $3>8 {print }’ /etc/passwd | 逻辑与,$1匹配mail,并且$3>8 |
awk -F: ‘{if($1~/mail/ && $3>8) print }’ /etc/passwd | |
awk -F: '$1~/mail/ | |
awk -F: '{if($1~/mail/ |
awk分为三部分:BEGIN{}+{正文}+END{}
[root@lzx ~]# awk 'BEGIN{print "姓名\t\t年龄\npj\t\t20\nzn\t\t13\nly\t16\nzy\t\t8"}'
姓名 年龄
pj 20
zn 13
ly 16
zy 8
[root@lzx ~]# awk 'NR!=1{print $2}' abc
20
13
16
8
模式匹配
当awk读入一行是时,它试图匹配脚本中的每个模式匹配规则。只有与一个特定的模式相匹配的输入行才能成为操作对象。如果没有指定操作,于模式相匹配的输入行将被打印出来
awk 常见调用正则表达式方法
awk语句中:
awk ‘/REG/{action}’
/REG/为正则表达式,可以将$0中,满足条件记录 送入到:action进行处理.
awk正则运算语句(~,~!等同!~)
[root@lzx ~]$ awk 'BEGIN{info="this is a test";if( info ~ /test/){print "ok"}}'
ok
awk内置使用正则表达式函数
gsub( Ere, Repl, [ In ] )
sub( Ere, Repl, [ In ] )
match( String, Ere )
split( String, A, [Ere] )
[root@lzx ~]# cat lzx
This line of data is ingored
[root@lzx ~]# awk '/^$/{print "This is a blank line."}' lzx
This is a blank line.
This is a blank line.
[root@lzx ~]# cat test
1 This is a book
2 What are you doing
3 The road is narrow
4 Have fun
// 过滤第一列大于 2 的行
[root@lzx ~]# awk '$1>2' test
3The road is narrow
4 Have fun
// 过滤第一列等于 3 的行,并输出第一列和第四列
[root@lzx ~]# awk '$1==3 {print $1,$4}' test
3 narrow
// 过滤第一列大于 1 并且第三列等于 ’are’ 的行
[root@lzx ~]# awk '$1>1 && $3=="are" {print $1,$2,$3}' test
2 what are
// 取第三行,不包含is 行的第二列和第四列输出
[root@lzx ~]# awk '$3 !~ /is/ {print $2,$4}' test
are doing
商品脚本
[root@lzx ~]# cat sss
炽天使 10
西游记 20
所罗门 12
农夫山泉 2
[root@lzx ~]# cat test.sh
#!/bin/bash
echo "商品列表:"
awk '{print NR".",$1,$2"元"}' sss
read -p "请输入要买的商品编号:" choice
read -p "请输入要买的数量:" num
awk -vcount=$num -vline=$choice 'NR==line{print "您一共买了"count"本"$1,"共消费"$2*count"元。"}' sss
[root@lzx ~]# bash test.sh
商品列表:
1. 炽天使 10
2. 西游记 20
3. 所罗门 12
4. 农夫山泉 2元
请输入商品编号:3
请输入数量:1
您一共买了1本书 共消费12元。