还不知道awk是什么,没关系,3分钟教会使用。
一、 介绍
Awk是一种用于操作数据和生成报告的脚本语言.awk命令编程语言不需要编译,并允许用户使用变量,数字函数,字符串函数和逻辑运算符。
Awk是一个实用程序,它使程序员能够以语句的形式编写微小但有效的程序,这些语句定义要在文档的每一行中搜索的文本模式以及在一个文档中找到匹配时要采取的操作。线。Awk主要用于模式扫描和处理。它搜索一个或多个文件以查看它们是否包含与指定模式匹配的行,然后执行相关操作。
用处:
(a)转换数据文件
(b)生成格式化报告
(c)格式输出行
(d)算术和字符串操作
(e)条件和循环
还不知道awk是什么,没关系,3分钟教会使用。
二、 用法
2.1 用法
awk option 'pattern{action}' input_filename > output_filename注意: 'pattern{action}' 是使用单引号,而不是双引号。
2.2 工作流程:
(a)逐行扫描文件
(b)将每个输入行拆分为字段
(c)将输入行/字段比较为模式
(d)在匹配的行上执行操作
2.2 选项
-F 指定列分隔符 -f 指定'pattern{action}'部分所在的文件 -v var_name = var_value设置变量:变量:
NR 保存当前行数 NF 保存当前行中列的数量,如果是空行NF的值为0 FS 保存列分隔符,用来每行分隔列使用。默认为white space(空白符,包括空格或者tab)。可以重新分配。建议在BEGIN中重新设置。 BEGIN { FS = ","} 重新设置成逗号。可以使用 -F "," 选项指定。 RS 保存当前行的分隔符,默认为\n. ORS 设置输出时每行结束分隔符,也就是行与行之前的分隔符。默认为\n。 一般在BEGIN中设置。 OFS 设置输出时每行字段之间的分隔符,默认 blank space(空格)。一般在BEGIN中设置。FIELDWIDTHS指定每隔字段的宽度(字段字符个数),例如 'BEGIN {FIELDWIDTHS = "3,4"} print $2,$3' , 代表$2字符长度最长为3,$3最长字符为4$0代表一整行的数据$n代表每一行的n列数据,例如$1 代表第一列,$2代表第二列特殊代码块
BEGIN { #code } : BEGIN 关键字后面的紧跟的第一个代码块({#code}),只会在第一行数据输入之前执行一次 END { #code} : END 关键字后面的紧跟的第一个代码块({#code}),只会在最后一行数据执行完以后执行一次 pattern { #code1} {#code2} : pattern返回结果为true时,执行code1,范围false时,不执行code1。但是code2都会执行。每行数据执行一次。 {print $1,$2,$3} : 打印字段1,字段2,字段3。字段之前使用逗号分隔,输出的时候逗号会被替换成OFS变量的值 next : 执行到next时,当前行不知执行next之后的代码(不管后面是什么都会执行),直接执行下一行输入还不知道awk是什么,没关系,3分钟教会使用。
三、 案例
假如我们有一个文件,内容如下(姓名 科目 分数):
[root@dongjing awk]# cat Tom Scala 30 Tom Scala 30 Tom Java 30 aJack Python 95 bJack Python 95 Jack Spring 95 Mike Java 95 Linda Linux 85 Linda PHP 66 Linda Linux 85 XY PHP 100 XY Java 55 Mike Scala 9 SS Shell 993.1 添加行号
[root@dongjing awk]# awk '{print NR,$0}' 1 Tom Scala 30 2 Tom Scala 30 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 7 Mike Java 95 8 Linda Linux 85 9 Linda PHP 66 10 Linda Linux 85 11 XY PHP 100 12 XY Java 55 13 14 Mike Scala 9 15 SS Shell 99 [root@dongjing sort]# cat -n 1 Tom Scala 30 2 Tom Scala 30 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 7 Mike Java 95 8 Linda Linux 85 9 Linda PHP 66 10 Linda Linux 85 11 XY PHP 100 12 XY Java 55 13 14 Mike Scala 9 15 SS Shell 993.2 过滤含有指定数据的行
awk 'patter' filename 或者 awk 'patter { print }' filenamea. 指定包含Java的行
# 使用awk [root@dongjing awk]# awk '/Java/' Tom Java 30 Mike Java 95 XY Java 55 [root@dongjing awk]# awk '/Java/ { print }' Tom Java 30 Mike Java 95 XY Java 55 # 使用 grep [root@dongjing awk]# grep Java Tom Java 30 Mike Java 95 XY Java 55 [root@dongjing awk]# grep "Java" Tom Java 30 Mike Java 95 XY Java 553.3 获取指定的行或者指定范围的行
a. 显示文件中的3-6行
[root@dongjing awk]# awk 'NR == 3 , NR == 6 { print NR,$0 }' 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 [root@dongjing awk]# awk '(NR >= 3) && ( NR <= 6) {print NR,$0}' 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 953.4 数据求和
a. 求score文件中所有科目分数之和(不能包含重复项)
[root@dongjing awk]# sort -u | awk 'NF > 0' | awk '{sum += $3 } END {print "Total Score: " sum }' Total Score: 854 # bc命令默认不安装,如果还没有安装请使用: yum install -y bc 安装即可 [root@dongjing awk]# sort -u | awk 'NF > 0'| awk ' $3 > 0 {ORS = "+"} {print $3}' | sed 's/\+$/\n/g'| bc 8543.5 打印非空行或者打印空行
a. 打印中的空行
[root@dongjing awk]# awk 'NF == 0 { print NR,$0 }' 13 [root@dongjing awk]# awk '/^$/ { print NR,$0 }' 13 # 打印空行或者全是空白符的行 [root@dongjing awk]# awk '/^\s*$/ { print NR,$0}' 13b. 打印中的非空行
# 注意这里没有13行,因为13行是空行 [root@dongjing awk]# awk 'NF > 0 { print NR,$0 }' 1 Tom Scala 30 2 Tom Scala 30 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 7 Mike Java 95 8 Linda Linux 85 9 Linda PHP 66 10 Linda Linux 85 11 XY PHP 100 12 XY Java 55 14 Mike Scala 9 15 SS Shell 99 [root@dongjing awk]# awk 'length($0) > 0 {print NR,$0} ' 1 Tom Scala 30 2 Tom Scala 30 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 7 Mike Java 95 8 Linda Linux 85 9 Linda PHP 66 10 Linda Linux 85 11 XY PHP 100 12 XY Java 55 14 Mike Scala 9 15 SS Shell 993.6 查找文件中最长行的字符数
打印文件中最长行的字符数
[root@dongjing awk]# awk '{if(length($0) > max) max = length($0)} END { print max}' 15 [root@dongjing awk]# wc -L 153.7 打印指定列满足条件的数据
打印第二列为Python学生姓名和成绩
[root@dongjing awk]# awk '{if($2 ~ /Python/) print NR,$1,$3 }' 4 aJack 95 5 bJack 95 [root@dongjing awk]# awk '{if($2 == "Python") print NR,$1,$3 }' 4 aJack 95 5 bJack 953.8 打印超过指定个数字符的行
打印文件中大于12个字符的行
# 查看每行字符数量 [root@dongjing awk]# awk '{ print NR,length($0),$0}' 1 12 Tom Scala 30 2 12 Tom Scala 30 3 11 Tom Java 30 4 15 aJack Python 95 5 15 bJack Python 95 6 14 Jack Spring 95 7 12 Mike Java 95 8 14 Linda Linux 85 9 12 Linda PHP 66 10 14 Linda Linux 85 11 10 XY PHP 100 12 10 XY Java 55 13 0 14 12 Mike Scala 9 15 11 SS Shell 99 # 查看大于12个字符的行 [root@dongjing awk]# awk 'length($0) > 12 { print NR,length($0),$0}' 4 15 aJack Python 95 5 15 bJack Python 95 6 14 Jack Spring 95 8 14 Linda Linux 85 10 14 Linda Linux 853.9 循环
a. 打印1-6平方的数据
[root@dongjing awk]# awk 'BEGIN { for(i=1;i<=6;i++) print i,"*",i,"=",i*i;}' 1 * 1 = 1 2 * 2 = 4 3 * 3 = 9 4 * 4 = 16 5 * 5 = 25 6 * 6 = 36 [root@dongjing awk]# awk 'BEGIN { for(i=1;i<=6;i++){ print i,"*",i,"=",i*i;}}' 1 * 1 = 1 2 * 2 = 4 3 * 3 = 9 4 * 4 = 16 5 * 5 = 25 6 * 6 = 363.10 打印文件总行数
[root@dongjing awk]# cat | wc -l 15 [root@dongjing awk]# awk 'END { print NR}' 15 [root@dongjing awk]# awk '{lines += 1} END { print lines }' 153.11 如何判断到达最后一行
在 最后一行添加 the end
[root@dongjing awk]# awk 'FNR == NR {last++;next}{print FNR, $0, ((last == FNR) ? "the end":"") }' 1 Tom Scala 30 2 Tom Scala 30 3 Tom Java 30 4 aJack Python 95 5 bJack Python 95 6 Jack Spring 95 7 Mike Java 95 8 Linda Linux 85 9 Linda PHP 66 10 Linda Linux 85 11 XY PHP 100 12 XY Java 55 13 14 Mike Scala 9 15 SS Shell 99 the end代码说明:
1. next : 如果执行next那么本行将不会执行next以后的代码,直接进入下一行计算。
2,. awk中一个匹配如果成立(结果为true或者1),那么会指定后面紧跟(最近)的代码块({}之间的内容),其他的代码块跟匹配条件没有关系。例如: 'FNR == NR {last++;next}{print FNR, $0, ((last == FNR) ? "the end":"") }' ,如果 FNR == NR 成立,则会执行{last++;next} 代码块,否则{last++;next} 不会执行。{print FNR, $0, ((last == FNR) ? "the end":"") } 代码块每次都会执行。
3.12 修改分隔符
a. 将文件中所有行的数据都即统一为一行,并且行之间使用:分隔
[root@dongjing awk]# awk '{ORS = ":"}{print}' | sed 's/:$/\n/' Tom Scala 30:Tom Scala 30:Tom Java 30:aJack Python 95:bJack Python 95:Jack Spring 95:Mike Java 95:Linda Linux 85:Linda PHP 66:Linda Linux 85:XY PHP 100:XY Java 55::Mike Scala 9:SS Shell 99b. 将score文件中每行列之间的分隔符都换成逗号
# 不生效 [root@dongjing awk]# awk '{OFS = ","}{print }' Tom Scala 30 Tom Scala 30 Tom Java 30 aJack Python 95 bJack Python 95 Jack Spring 95 Mike Java 95 Linda Linux 85 Linda PHP 66 Linda Linux 85 XY PHP 100 XY Java 55 Mike Scala 9 SS Shell 99 # 不生效 [root@dongjing awk]# awk '{OFS = ","}{print $0}' Tom Scala 30 Tom Scala 30 Tom Java 30 aJack Python 95 bJack Python 95 Jack Spring 95 Mike Java 95 Linda Linux 85 Linda PHP 66 Linda Linux 85 XY PHP 100 XY Java 55 Mike Scala 9 SS Shell 99 # 打印的时候需要指定每个字段 [root@dongjing awk]# awk '{OFS = ","}{print $1,$2,$3 }' Tom,Scala,30 Tom,Scala,30 Tom,Java,30 aJack,Python,95 bJack,Python,95 Jack,Spring,95 Mike,Java,95 Linda,Linux,85 Linda,PHP,66 Linda,Linux,85 XY,PHP,100 XY,Java,55 ,, Mike,Scala,9 SS,Shell,993.找到没门学科中分数前两名的学生信息(相同分数排名依次向下)
# 排序去重 [root@dongjing awk]# sort -u aJack Python 95 bJack Python 95 Jack Spring 95 Linda Linux 85 Linda PHP 66 Mike Java 95 Mike Scala 9 SS Shell 99 Tom Java 30 Tom Scala 30 XY Java 55 XY PHP 100 # 去取空行 [root@dongjing awk]# sort -u | awk 'NF > 0' aJack Python 95 bJack Python 95 Jack Spring 95 Linda Linux 85 Linda PHP 66 Mike Java 95 Mike Scala 9 SS Shell 99 Tom Java 30 Tom Scala 30 XY Java 55 XY PHP 100 # 按照学科和分数排序,学科是第一排序,分数是第二排序。相当于SQL: order by course, score desc [root@dongjing awk]# sort -u | awk 'NF > 0' | sort -k2,2 -k3,3gr Mike Java 95 XY Java 55 Tom Java 30 Linda Linux 85 XY PHP 100 Linda PHP 66 aJack Python 95 bJack Python 95 Tom Scala 30 Mike Scala 9 SS Shell 99 Jack Spring 95 # 对每一个学科取前两名。 相当于SQL中使用开窗函数 [root@dongjing awk]# sort -u | awk 'NF > 0' | sort -k2,2 -k3,3gr | awk '((last == $2) || (last == ""))&&(limit < 2){limit++; print; } (last != $2 )&&(last != "" ){limit = 1; print} {last = $2}' Mike Java 95 XY Java 55 Linda Linux 85 XY PHP 100 Linda PHP 66 aJack Python 95 bJack Python 95 Tom Scala 30 Mike Scala 9 SS Shell 99 Jack Spring 95