三剑客:awk实战
1 awk实战基础入门精讲
1.1 awk命令格式:
awk指令由模式、动作、或者模式和动作的组合组成
模式既pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的政策表达式。比如NR==,这就是模式,可以把他理解位一个条件。
动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。如awk使用格式
1.1.1 常见的模式类型:
1、Regexp: 正则表达式,格式为/regular expression/
2、expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和!~(不匹配)。
3、Ranges: 指定的匹配范围,格式为pat1,pat2
4、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
5、Empty(空模式):匹配任意输入行;
1.1.2 常见的Action
1、Expressions:
2、Control statements
3、Compound statements
4、Input statements
5、Output statements
1.2 awk的执行过程
系统环境
[root@cobbler6 ~]# cat /etc/redhat-release CentOS release 6.7 (Final) [root@cobbler6 ~]# uname -r 2.6.32-573.el6.x86_64 [root@cobbler6 ~]# ll "which awk" ls: cannot access which awk: No such file or directory [root@cobbler6 ~]# ll `which awk` lrwxrwxrwx. 1 root root 4 Oct 7 01:03 /bin/awk -> gawk [root@cobbler6 ~]# awk --version GNU Awk 3.1.7
示例文件:
[root@cobbler6 ~]# mkdir /server/files/ -p [root@cobbler6 ~]# head /etc/passwd >/server/ files/ scripts/ [root@cobbler6 ~]# head /etc/passwd >/server/files/awkfile.txt [root@cobbler6 ~]# cat awkfile.txt cat: awkfile.txt: No such file or directory [root@cobbler6 ~]# cat /server//files/awkfile.txt root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
1.3 记录和域的概念
[root@cobbler6 files]# awk 'BEGIN{RS=":"}{print NR,$0}' awkfile.txt 1 root 2 x 3 0 4 0 5 root 6 /root 7 /bin/bash bin 8 x
awk眼中的文件,从头到尾一段连续的字符串,恰巧中间有些\n(回车换行符),为了方便人查看,就把RS的值设置为\n
[root@cobbler6 files]# awk 'BEGIN{RS=""}{print NR,$0}' awkfile.txt 1 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin [root@cobbler6 files]# awk 'BEGIN{RS=""}{print NR,$1,$3,#5}' awkfile.txt awk: cmd. line:1: BEGIN{RS=""}{print NR,$1,$3,#5} awk: cmd. line:1: ^ syntax error [root@cobbler6 files]# awk 'BEGIN{RS=""}{print NR,$1,$3,$5}' awkfile.txt 1 root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
企业案例1:计算文件中每个单词重复数量
1、单词弄成一列(排队)
sed -ri.bak 's#[:/0-9]+# #g' awkfile.txt RS 替换\n [root@cobbler6 files]# egrep -o "[a-zA-Z]+" awkfile.txt |sort|uniq -c 3 adm 1 bash 5 bin 2 daemon 3 halt 2 lp 1 lpd 3 mail 6 nologin 3 root 12 sbin 3 shutdown 3 spool 3 sync 3 uucp 4 var 10 x RS 空值 [root@cobbler6 files]# sed -ri.bak 's#[:/0-9]+# #g' awkfile.txt 去掉[:/0-9] [root@cobbler6 files]# cat awkfile.txt root x root root bin bash bin x bin bin sbin nologin daemon x daemon sbin sbin nologin adm x adm var adm sbin nologin lp x lp var spool lpd sbin nologin sync x sync sbin bin sync shutdown x shutdown sbin sbin shutdown halt x halt sbin sbin halt mail x mail var spool mail sbin nologin uucp x uucp var spool uucp sbin nologin
2、统计
egrep -o "[a-zA-Z]+" awkfile.txt |sort|uniq –c awk 'BEGIN{RS="()|\n"}{print NR,$0}' awkfile.txt |sort|uniq -c|sort –rn
企业按案例2:计算文件中重复的数量
1.3.1 记录小结:
- 大象放冰箱分几步?打开冰箱,把大象放进去,关闭冰箱门。
- 多使用,NR,NF,$数字,配合你调试你的awk命令
- NR number of record存放着每个记录的号(行号)读取新行时候会自动+1
- RS record separate是输入数据的记录的分隔符,简单理解就是可以指定每个记录的记录结尾标记
- (用RS替换\n)
- RS 作用就是表示一个记录的结束
- FS 表示着每个区域的结束
1.3.2 小结:
- $ 表示取区域,$1,$2 NF,$NF
- NF number of fileds 表示记录中的区域数量,$NF取最后一个区域
- FS(-F) filed separate区域分隔符,
- RS
- NR
- 选好合适的刀FS(***),RS,OFS,ORS
- $1,$3,$数字 选中你要处理的区域
- 分隔符==》结束表示
- 记录与区域,你就对我们所谓的行与列,有了新的认识。
用于第二行或第五行
[root@cobbler6 files]# awk 'NR==2||NR==5{print $1,$3}' awkfile.txt bin bin lp lp
FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
ARGC: awk命令的参数的个数;
FILENAME: awk命令所处理的文件的名称;
ENVIRON:当前shell环境变量及其值的关联数组;
1.4 正则表达式
[root@cobbler6 files]# awk -F "/" '$(NF-1)~/^bin/{print NF,$0,$3}' /etc/passwd 4 root:x:0:0:root:/root:/bin/bash bin 4 sync:x:5:0:sync:/sbin:/bin/sync bin 5 asdfghg:x:503:503::/home/asdfghg:/bin/bash asdfghg: 5 chujiyw001:x:809:809::/home/chujiyw001:/bin/bash chujiyw001: 5 chujiyw002:x:810:810::/home/chujiyw002:/bin/bash chujiyw002: 5 chujiyw003:x:811:811::/home/chujiyw003:/bin/bash chujiyw003: 5 ywsenior001:x:812:812::/home/ywsenior001:/bin/bash ywsenior001: 5 ywmanager001:x:813:813::/home/ywmanager001:/bin/bash ywmanager001: 5 chujikf001:x:814:814::/home/chujikf001:/bin/bash chujikf001: 5 chujikf002:x:815:815::/home/chujikf002:/bin/bash chujikf002: 5 kfsenior001:x:816:816::/home/kfsenior001:/bin/bash kfsenior001: 5 kfmanager001:x:817:817::/home/kfmanager001:/bin/bash kfmanager001: 5 jiak001:x:818:818::/home/jiak001:/bin/bash jiak001: 5 jiak002:x:819:819::/home/jiak002:/bin/bash jiak002: 5 chjidba001:x:820:820::/home/chjidba001:/bin/bash chjidba001: 5 chjidba002:x:821:821::/home/chjidba002:/bin/bash chjidba002: 5 chjidba003:x:822:822::/home/chjidba003:/bin/bash chjidba003: 5 dbasenior001:x:823:823::/home/dbasenior001:/bin/bash dbasenior001: 5 chjidwg001:x:824:824::/home/chjidwg001:/bin/bash chjidwg001: 5 chjidwg002:x:825:825::/home/chjidwg002:/bin/bash chjidwg002: 5 wgsenior001:x:826:826::/home/wgsenior001:/bin/bash wgsenior001:
[root@cobbler6 files]# awk -F "/" '$(NF-1)~/^bin/{print NF,$3}' /etc/passwd 4 bin 4 bin 5 asdfghg: 5 chujiyw001: 5 chujiyw002: 5 chujiyw003: 5 ywsenior001: 5 ywmanager001: 5 chujikf001: 5 chujikf002: 5 kfsenior001: 5 kfmanager001: 5 jiak001: 5 jiak002: 5 chjidba001: 5 chjidba002: 5 chjidba003: 5 dbasenior001: 5 chjidwg001: 5 chjidwg002: 5 wgsenior001: [root@cobbler6 files]# awk -F "/" '$(NF-1)~/^bin/{print NF,$0,$3}' /etc/passwd 4 root:x:0:0:root:/root:/bin/bash bin 4 sync:x:5:0:sync:/sbin:/bin/sync bin 5 asdfghg:x:503:503::/home/asdfghg:/bin/bash asdfghg: 5 chujiyw001:x:809:809::/home/chujiyw001:/bin/bash chujiyw001: 5 chujiyw002:x:810:810::/home/chujiyw002:/bin/bash chujiyw002: 5 chujiyw003:x:811:811::/home/chujiyw003:/bin/bash chujiyw003: 5 ywsenior001:x:812:812::/home/ywsenior001:/bin/bash ywsenior001: 5 ywmanager001:x:813:813::/home/ywmanager001:/bin/bash ywmanager001: 5 chujikf001:x:814:814::/home/chujikf001:/bin/bash chujikf001: 5 chujikf002:x:815:815::/home/chujikf002:/bin/bash chujikf002: 5 kfsenior001:x:816:816::/home/kfsenior001:/bin/bash kfsenior001: 5 kfmanager001:x:817:817::/home/kfmanager001:/bin/bash kfmanager001: 5 jiak001:x:818:818::/home/jiak001:/bin/bash jiak001: 5 jiak002:x:819:819::/home/jiak002:/bin/bash jiak002: 5 chjidba001:x:820:820::/home/chjidba001:/bin/bash chjidba001: 5 chjidba002:x:821:821::/home/chjidba002:/bin/bash chjidba002: 5 chjidba003:x:822:822::/home/chjidba003:/bin/bash chjidba003: 5 dbasenior001:x:823:823::/home/dbasenior001:/bin/bash dbasenior001: 5 chjidwg001:x:824:824::/home/chjidwg001:/bin/bash chjidwg001: 5 chjidwg002:x:825:825::/home/chjidwg002:/bin/bash chjidwg002: 5 wgsenior001:x:826:826::/home/wgsenior001:/bin/bash wgsenior001: [root@cobbler6 files]# awk -F ":" '$NF~/bash$/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash asdfghg:x:503:503::/home/asdfghg:/bin/bash chujiyw001:x:809:809::/home/chujiyw001:/bin/bash chujiyw002:x:810:810::/home/chujiyw002:/bin/bash chujiyw003:x:811:811::/home/chujiyw003:/bin/bash ywsenior001:x:812:812::/home/ywsenior001:/bin/bash ywmanager001:x:813:813::/home/ywmanager001:/bin/bash chujikf001:x:814:814::/home/chujikf001:/bin/bash chujikf002:x:815:815::/home/chujikf002:/bin/bash kfsenior001:x:816:816::/home/kfsenior001:/bin/bash kfmanager001:x:817:817::/home/kfmanager001:/bin/bash jiak001:x:818:818::/home/jiak001:/bin/bash jiak002:x:819:819::/home/jiak002:/bin/bash chjidba001:x:820:820::/home/chjidba001:/bin/bash chjidba002:x:821:821::/home/chjidba002:/bin/bash chjidba003:x:822:822::/home/chjidba003:/bin/bash dbasenior001:x:823:823::/home/dbasenior001:/bin/bash chjidwg001:x:824:824::/home/chjidwg001:/bin/bash chjidwg002:x:825:825::/home/chjidwg002:/bin/bash wgsenior001:x:826:826::/home/wgsenior001:/bin/bas [root@cobbler6 files]# awk -F "/" '$NF~/^bash$/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash asdfghg:x:503:503::/home/asdfghg:/bin/bash chujiyw001:x:809:809::/home/chujiyw001:/bin/bash chujiyw002:x:810:810::/home/chujiyw002:/bin/bash chujiyw003:x:811:811::/home/chujiyw003:/bin/bash ywsenior001:x:812:812::/home/ywsenior001:/bin/bash ywmanager001:x:813:813::/home/ywmanager001:/bin/bash chujikf001:x:814:814::/home/chujikf001:/bin/bash chujikf002:x:815:815::/home/chujikf002:/bin/bash kfsenior001:x:816:816::/home/kfsenior001:/bin/bash kfmanager001:x:817:817::/home/kfmanager001:/bin/bash jiak001:x:818:818::/home/jiak001:/bin/bash jiak002:x:819:819::/home/jiak002:/bin/bash chjidba001:x:820:820::/home/chjidba001:/bin/bash chjidba002:x:821:821::/home/chjidba002:/bin/bash chjidba003:x:822:822::/home/chjidba003:/bin/bash dbasenior001:x:823:823::/home/dbasenior001:/bin/bash chjidwg001:x:824:824::/home/chjidwg001:/bin/bash chjidwg002:x:825:825::/home/chjidwg002:/bin/bash wgsenior001:x:826:826::/home/wgsenior001:/bin/bash
[root@cobbler6 files]# awk 'NR==2,NR==5{print $1,$3}' awkfile.txt bin bin daemon daemon adm adm lp lp
1.4.1 正则表达式小结:
1) 模式 ==》条件
2) 正则表达式
3) 条件表达式(NR>=2 NR==2),
4) 范围表达式 NR==2,NR==5)
5) /正则表达式-开始/,/正则结束/
6) $1~/正则表达式-开始/,$3~/正则结束/ 行,记录。
7) 区域:FS刀分隔的,FS区域分隔符
8) 记录:RS刀分隔符,RS记录分隔符
9) FS===>NF区域的数量
10) RS===>NR记录号,随着记录的增加 NR自动+1
7.1 常见的模式类型:
1、Regexp: 正则表达式,格式为/regular expression/
2、expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和!~(不匹配)。
3、Ranges: 指定的匹配范围,格式为pat1,pat2
4、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
5、Empty(空模式):匹配任意输入行;
2 awk实战基础入门精讲
2.1 BENGIN模块和END模块
BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
END:让用户在最后一条输入记录被读取之后发生的动作。
[root@cobbler6 files]# awk 'BEGIN{print "Hello world!"}' Hello world! [root@cobbler6 files]# awk 'BEGIN{RS="/"}{print NF $0}' awkfile2.txt 1root:x:0:0:root: 1root: 1bin 2bash bin:x:1:1:bin [root@cobbler6 files]# grep -c "^$" /etc/services 16 [root@cobbler6 files]# awk '/^$/{a=a+1}END{print a}' /etc/services 16
企业案例3:统计文件里面的空行数量
[root@cobbler6 ~]# awk '/^$/{a=a+1;print a}' /etc/services 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@cobbler6 ~]# awk '/^$/{a=a+1}END{print a}' /etc/services 16
sed怎么调试,正则表达式调试
企业面试题4:awkfile2.txt里面 以:为分隔符,区域3大于15行,一共有多少行?
[root@cobbler6 files]# awk -F ":" '$3>15{a++}END{print a}' awkfile2.txt 6 [root@cobbler6 files]# awk -F ":" '$3>15{a++;print a}END{print a}' awkfile2.txt 1 2 3 4 5 6 6 [root@cobbler6 files]# awk -F ":" 'BEGIN{print FS}'
2.1.1 总结:
2.2 预定义变量简介
2.3 awk数组
[root@cobbler6 files]# awk 'BEGIN{oldboy["a"]="oldgirl";oldboy["b"]="xiaoyu";oldloy["c"]="oldboy" print oldboy["a"] print oldboy["b"] print oldloy["c"] }' oldgirl xiaoyu oldboy
awk数组的元素名(苹果名字)可以是字符串
字符串要使用双引号引起来""
[root@cobbler6 files]# awk -F "/" '{array[$3];print $3}' awkfile3.txt www.etiantian.org www.etiantian.org post.etiantian.org mp3.etiantian.org www.etiantian.org post.etiantian.org [root@cobbler6 files]# awk -F "/" '$3~/www.etiantian.org/' awkfile3.txt http://www.etiantian.org/index.html http://www.etiantian.org/1.html http://www.etiantian.org/3.html [root@cobbler6 files]# awk -F "/" '$3~/www.etiantian.org/{print $3}' awkfile3.txt www.etiantian.org www.etiantian.org www.etiantian.org [root@cobbler6 files]# awk -F "/" '$3~/www.etiantian.org/{array[e]}' awkfile3.txt [root@cobbler6 files]# awk -F "/" '$3~/www.etiantian.org/{array["www.etiantian.org"]++;print array["www.etiantian.org"]}' awkfile3.txt 1 2 3 [root@cobbler6 files]# awk -F "/" '{array[$3]++;print $3,array[$3]}' awkfile3.txt www.etiantian.org 1 www.etiantian.org 2 post.etiantian.org 1 mp3.etiantian.org 1 www.etiantian.org 3 post.etiantian.org 2
2.3.1 数组总结
- awk数组去重
- 选好分隔符 -F "/"
- 选好处理的区域,print $1,$3,$2
- array[$3]++
- 先处理,最后END模块输出
- 输出awk数组我们使用for(key in arry)
- =>for() 循环
- key in array手去筐里 抓苹果
- key就是苹果名字(框的的名字)
- array数组名(框的名字)
- 打印输出print key,array[key]
3、控制语句:
8.1 if-else
语法:if (condition) {then-body} else {[ else-body ]}
例子:
awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
3.2 while
语法: while (condition){statement1; statment2; ...}
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
3.3 do-while
语法: do {statement1, statement2, ...} while (condition)
awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
3.4 for
语法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd
for循环还可以用来遍历数组元素:
语法: for (i in array) {statement1, statement2, ...}
awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
3.5 case
语法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
3.6 break 和 continue
常用于循环或case语句中
3.7 next
提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:
# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
4.4 awk英语
[root@cobbler6 files]# awk '{print NR,$0}' 20-30.txt 50-60.txt 1 20 2 21 3 22 4 23 5 24 6 25 7 26 8 27 9 28 10 29 11 30 12 50 13 51 14 52 15 53 16 54 17 55 18 56 19 57 20 58 21 59 22 60 [root@cobbler6 files]# awk '{print FNR,NR,$0}' 20-30.txt 50-60.txt 1 1 20 2 2 21 3 3 22 4 4 23 5 5 24 6 6 25 7 7 26 8 8 27 9 9 28 10 10 29 11 11 30 1 12 50 2 13 51 3 14 52 4 15 53 5 16 54 6 17 55 7 18 56 8 19 57 9 20 58 10 21 59 11 22 60
5、print
print的使用格式:
print item1, item2, ...
要点:
1、各项目之间使用逗号隔开,而输出时则以空白字符分隔;
2、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
3、print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";
例子:
# awk 'BEGIN { print "line one\nline two\nline three" }' awk -F: '{ print $1, $3 }' /etc/passwd
6、printf
printf命令的使用格式:
printf format, item1, item2, ...
要点:
1、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符;\n
format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码; %d, %i:十进制整数; %e, %E:科学计数法显示数值; %f: 显示浮点数; %g, %G: 以科学计数法的格式或浮点数的格式显示数值; %s: 显示字符串; %u: 无符号整数; %%: 显示%自身;
修饰符:
N: 显示宽度; -: 左对齐; +:显示数值符号;
例子:
# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd
7、输出重定向
print items > output-file print items >> output-file print items | command
特殊文件描述符:
/dev/stdin:标准输入 /dev/sdtout: 标准输出 /dev/stderr: 错误输出 /dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
例子:
# awk -F: '{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }' /etc/passwd
7、awk的操作符:
7.1 算术操作符:
-x: 负值 +x: 转换为数值; x^y: x**y: 次方 x*y: 乘法 x/y:除法 x+y: x-y: x%y:
7.2 字符串操作符:
只有一个,而且不用写出来,用于实现字符串连接;
7.3 赋值操作符:
= += -= *= /= %= ^= **= ++ --
需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;
7.4 布尔值
awk中,任何非0值或非空字符串都为真,反之就为假;
7.5 比较操作符:
x < y True if x is less than y. x <= y True if x is less than or equal to y. x > y True if x is greater than y. x >= y True if x is greater than or equal to y. x == y True if x is equal to y. x != y True if x is not equal to y. x ~ y True if the string x matches the regexp denoted by y. x !~ y True if the string x does not match the regexp denoted by y. subscript in array True if the array array has an element with the subscript subscript.
7.7 表达式间的逻辑关系符:
&&
||
7.8 条件表达式:
selector?if-true-exp:if-false-exp if selector; then if-true-exp else if-false-exp fi a=3 b=4 a>b?a is max:b ia max
7.9 函数调用:
function_name (para1,para2)
生产常用功能总结
1、显示出某个范围内的内容
awk 'NR==20,NR==30' fliename
2、通过awk统计计算
awk '{sum+=$0}END{print sum}'
3、awk数组计算与去重
awk '{array[$1]++}END{for(key in array)print key,array[key]}' access.log awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd root Admin bin Common User daemon Common User
awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd root : Admin bin : Common User daemon : Common User awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
4、awk 实现给文件的每行内容之前加上行号
awk '{print NR,$0}'
5、显示第二到第六行
awk 'NR==2,NR==6 {print NR,$0}'
6、替换功能
awk '{gsub("/sbin/nologin","/bin/bash",$0);print $0}' awk '{gsub("替换对象","替换成什么内容",那一列);print $0}'
注意:
- gsub与后面的括号之间不能有空格
- 替换对象、替换成什么内容以及那一列之间要用逗号隔开
- 替换队形的外面要有双引号或双斜线包裹起来,即"替换对象"或/替换对象/
- 替换成什么内容就只能用双引号括起来了,即"替换成什么内容"
- 最后一个是那一列,这个是可以省略的,省略的时候表示要替换整行的内容,相当于写上$0
八、常见awk用法
##提取两个文件第一列相同的行 awk -F',' 'NR==FNR{a[$1]=$0;next}NR>FNR{if($1 in a)print $0"\n"a[$1]}' 1.log 2.log awk 'NR==FNR{a[$1]++}NR>FNR&&a[$1]>1' 111.txt 111.txt awk 'a[$1]++==1' cat 111.txt | awk -F '[:|]' '{print $2}' > 111.txt ##awk 按某个位置的字符分隔的方法 awk -F ":" '{ for(i=1;i<=3;i++) printf("%s:",$i)}' awk -F':' '{print $1 ":" $2 ":" $3; print $4}' awk -F':' '{print $1 ":" $2 ":" $3; for(i=1;i<=3;i++)$i=""; print}' ##awk打印用户和密码 cat test.log |awk -F '[ ]+' '{print $1 " " $2}' ##排序显示重复项目 cat test.log |awk -F '[ ]+' '{print $1}'| sort | uniq -c | sort -nr #awk -F '\t'来表示分隔符,比如 awk -F '\t' '{print $1}' file1.txt ##多个空格分隔的方法 awk -F '[ ]+' '{print $9}' ls -lh /etc/sysconfig/network-scripts/ifcfg-* | awk -F '[ ]+' '{print $9}' ##指定分隔符既可以为空格,又可以为冒号,那么处理将会变得简单。可以使用正则表达式来指定多个分隔符,格式为 -F'[空格:]+' 如下 awk -F'[ :]+' '{print $NF"\t"$(NF-2)}' file1.txt 1、awk '/101/' file 显示文件file中包含101的匹配行。 awk '/101/,/105/' file awk '$1 == 5' file awk '$1 == "CT"' file 注意必须带双引号 awk '$1 * $2 >100 ' file awk '$2 >5 && $2<=15' file 2、awk '{print NR,NF,$1,$NF,}' file 显示文件file的当前记录号、域数和每一行的第一个和最后一个域。 awk '/101/ {print $1,$2 + 10}' file 显示文件file的匹配行的第一、二个域加10。 awk '/101/ {print $1$2}' file awk '/101/ {print $1 $2}' file 显示文件file的匹配行的第一、二个域,但显示时域中间没有分隔符。 3、df | awk '$4>1000000 ' 通过管道符获得输入,如:显示第4个域满足条件的行。 4、awk -F "|" '{print $1}' file 按照新的分隔符“|”进行操作。 awk 'BEGIN { FS="[: \t|]" } {print $1,$2,$3}' file 通过设置输入分隔符(FS="[: \t|]")修改输入分隔符。 Sep="|" awk -F $Sep '{print $1}' file 按照环境变量Sep的值做为分隔符。 awk -F '[ :\t|]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。 awk -F '[][]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表[、] 5、awk -f awkfile file 通过文件awkfile的内容依次进行控制。 cat awkfile /101/{print "\047 Hello! \047"} --遇到匹配行以后打印 ' Hello! '. \047代表单引号。 {print $1,$2} --因为没有模式控制,打印每一行的前两个域。 6、awk '$1 ~ /101/ {print $1}' file 显示文件中第一个域匹配101的行(记录)。 7、awk 'BEGIN { OFS="%"} {print $1,$2}' file 通过设置输出分隔符(OFS="%")修改输出格式。 8、awk 'BEGIN { max=100 ;print "max=" max} BEGIN 表示在处理任意行之前进行的操作。 {max=($1 >max ?$1:max); print $1,"Now max is "max}' file 取得文件第一个域的最大值。 (表达式1?表达式2:表达式3 相当于: if (表达式1) 表达式2 else 表达式3 awk '{print ($1>4 ? "high "$1: "low "$1)}' file 9、awk '$1 * $2 >100 {print $1}' file 显示文件中第一个域匹配101的行(记录)。 10、awk '{$1 == 'Chi' {$3 = 'China'; print}' file 找到匹配行后先将第3个域替换后再显示该行(记录)。 awk '{$7 %= 3; print $7}' file 将第7域被3除,并将余数赋给第7域再打印。 11、awk '/tom/ {wage=$2+$3; printf wage}' file 找到匹配行后为变量wage赋值并打印该变量。 12、awk '/tom/ {count++;} END {print "tom was found "count" times"}' file END表示在所有输入行处理完后进行处理。 13、awk 'gsub(/\$/,"");gsub(/,/,""); cost+=$4; END {print "The total is $" cost>"filename"}' file gsub函数用空串替换$和,再将结果输出到filename中。 1 2 3 $1,200.00 1 2 3 $2,300.00 1 2 3 $4,000.00 awk '{gsub(/\$/,"");gsub(/,/,""); if ($4>1000&&$4<2000) c1+=$4; else if ($4>2000&&$4<3000) c2+=$4; else if ($4>3000&&$4<4000) c3+=$4; else c4+=$4; } END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file 通过if和else if完成条件语句 awk '{gsub(/\$/,"");gsub(/,/,""); if ($4>3000&&$4<4000) exit; else c4+=$4; } END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file 通过exit在某条件时退出,但是仍执行END操作。 awk '{gsub(/\$/,"");gsub(/,/,""); if ($4>3000) next; else c4+=$4; } END {printf "c4=[%d]\n",c4}"' file 通过next在某条件时跳过该行,对下一行执行操作。 14、awk '{ print FILENAME,$0 }' file1 file2 file3>fileall 把file1、file2、file3的文件内容全部写到fileall中,格式为 打印文件并前置文件名。 15、awk ' $1!=previous { close(previous); previous=$1 } {print substr($0,index($0," ") +1)>$1}' fileall 把合并后的文件重新分拆为3个文件。并与原文件一致。 16、awk 'BEGIN {"date"|getline d; print d}' 通过管道把date的执行结果送给getline,并赋给变量d,然后打印。 17、awk 'BEGIN {system("echo \"Input your name:\\c\""); getline d;print "\nYour name is",d,"\b!\n"}' 通过getline命令交互输入name,并显示出来。 awk 'BEGIN {FS=":"; while(getline< "/etc/passwd" >0) { if($1~"050[0-9]_") print $1}}' 打印/etc/passwd文件中用户名包含050x_的用户名。 18、awk '{ i=1;while(i<NF) {print NF,$i;i++}}' file 通过while语句实现循环。 awk '{ for(i=1;i<NF;i++) {print NF,$i}}' file 通过for语句实现循环。 type file|awk -F "/" ' { for(i=1;i<NF;i++) { if(i==NF-1) { printf "%s",$i } else { printf "%s/",$i } }}' 显示一个文件的全路径。 用for和if显示日期 awk 'BEGIN { for(j=1;j<=12;j++) { flag=0; printf "\n%d月份\n",j; for(i=1;i<=31;i++) { if (j==2&&i>28) flag=1; if ((j==4||j==6||j==9||j==11)&&i>30) flag=1; if (flag==0) {printf "%02d%02d ",j,i} } } }'