awk 是一个强大的文本分析工具,把文件逐行的读入,以空格为默认分割符将每行切片,切开的部分再进行各种分析处理。
awk命令形式:
awk [-F | -f | -v] `BEGIN{} // {command1;command2;....;commandN} END{}` file
[-F | -f | -v] : 大参数,-F指定分隔符,-f调用脚本,-v定义变量
` ` : 引用代码块
BEGIN : 初始化代码块,在对每一行进行处理之前,初始化代码,(在脚本中主要是引用全局变量,设置FS分隔符)
// : 匹配样式,可以是字符串或者正则表达式
{} : 命令代码块,包含一条或者多条命令
; : 多条命令使用分号分隔
END : 结尾代码块,在对每一行进行处理之后在执行的代码块,主要是进行最终计算或输出结尾摘要信息。
awk 支持的算术运算:
+ - * / ^ % ++ -- += -= *= /= %=
awk 内置变量:
$0 表示整个当前行
$n 每行第n个字段,n不能为0
NF 字段数量变量
NR 每行的记录号,多文件处理是记录递增
FNR 每行的记录号,多文件处理时不递增,每个文件都从1开始
FS BEGIN时定义分隔符
RS 输入的记录分隔符,默认为换行符
OFS 输出字段分隔符,默认是空格
ORS 输出记录的分隔符,默认是换行符
示例文件emp_names
$ cat emp_names 46013 DURHAM JEFF MOBILE AL 46015 STEEN BILL MOBILE AL 46017 FELDMAN EVAN MOBILE AL 46018 SWIM STEVE UNKNOWN AL 46019 BOGUE ROBERT PHOENIX AZ 46021 JUNE MICAH PHOENIX AZ 46022 KANE SHERYL UNKNOWN AR 46024 WOOD WILLIAM MUNCIE IN 46026 FERGUS SARAH MUNCIE IN 46027 BUCK SARAH MUNCIE IN 46029 TUTTLE BOB MUNCIE IN
$ awk '{print $0}' emp_names #打印文件emp_names中的所有字段 46013 DURHAM JEFF MOBILE AL 46015 STEEN BILL MOBILE AL 46017 FELDMAN EVAN MOBILE AL 46018 SWIM STEVE UNKNOWN AL 46019 BOGUE ROBERT PHOENIX AZ 46021 JUNE MICAH PHOENIX AZ 46022 KANE SHERYL UNKNOWN AR 46024 WOOD WILLIAM MUNCIE IN 46026 FERGUS SARAH MUNCIE IN 46027 BUCK SARAH MUNCIE IN 46029 TUTTLE BOB MUNCIE IN $ awk '{print $1,$2,$3,$4,$5}' emp_names #打印文件emp_names中多个字段 46013 DURHAM JEFF MOBILE AL 46015 STEEN BILL MOBILE AL 46017 FELDMAN EVAN MOBILE AL 46018 SWIM STEVE UNKNOWN AL 46019 BOGUE ROBERT PHOENIX AZ 46021 JUNE MICAH PHOENIX AZ 46022 KANE SHERYL UNKNOWN AR 46024 WOOD WILLIAM MUNCIE IN 46026 FERGUS SARAH MUNCIE IN 46027 BUCK SARAH MUNCIE IN 46029 TUTTLE BOB MUNCIE IN
$ awk '/AL|AZ/ {print $3,$2,$5}' emp_names #打印文件emp_names中匹配AL 、 AZ样式的多个字段 JEFF DURHAM AL BILL STEEN AL EVAN FELDMAN AL STEVE SWIM AL ROBERT BOGUE AZ MICAH JUNE AZ $ awk '$5~/AR/' emp_names #在第5个字段中匹配样式,没有指定打印字段,则打印所有字段 46022 KANE SHERYL UNKNOWN AR $ awk '$5!~/AR/' emp_names #在第5个字段中匹配样式,打印出不匹配的所有行(没有指定打印字段,打印所有字段) 46013 DURHAM JEFF MOBILE AL 46015 STEEN BILL MOBILE AL 46017 FELDMAN EVAN MOBILE AL 46018 SWIM STEVE UNKNOWN AL 46019 BOGUE ROBERT PHOENIX AZ 46021 JUNE MICAH PHOENIX AZ 46024 WOOD WILLIAM MUNCIE IN 46026 FERGUS SARAH MUNCIE IN 46027 BUCK SARAH MUNCIE IN 46029 TUTTLE BOB MUNCIE IN $ awk '$5~/AR/ {print $1 ; print $2 ; print $3}' emp_names #将一行中多个字段分行打印 46022 KANE SHERYL
$ awk '{print $0 | "sort > /tmp/filez"} ' emp_names #将文件emp_names中字段排序,重定向到/tmp/filez文件中 $ cat /tmp/filez 46011 TUTTLE BOB MUNCIE IN 46012 STEEN BILL MOBILE AL 46013 DURHAM JEFF MOBILE AL 46017 FELDMAN EVAN MOBILE AL 46018 BOGUE ROBERT PHOENIX AZ 46019 SWIM STEVE UNKNOWN AL 46021 JUNE MICAH PHOENIX AZ 46022 KANE SHERYL UNKNOWN AR 46027 BUCK SARAH MUNCIE IN 46030 FERGUS SARAH MUNCIE IN 46045 WOOD WILLIAM MUNCIE IN
$ awk -F":" '{print $1}' /etc/passwd #/etc/passwd是系统自带文件 每行是用:分隔字符,所以需要指定分隔符 也可以使用 awk '{FS=":"} {print $1}' /etc/passwd 这样结果是一样的 root daemon bin sys sync games man lp mail news ...
$ cat awk.list BEGIN{FS=":"} {print $1} $ awk -f awk.list /etc/passwd #使用-f调用awk脚本 root daemon bin sys sync games man lp
$ awk '{FS=":"} {OFS="-"}{print $1,$3}' /etc/passwd #指定输出字段分隔符 root:x:0:0:root:/root:/bin/bash- daemon-1 bin-2 sys-3 sync-4 games-5 man-6 lp-7 $ awk -F":" '{print "USER_NAME: "$1, "\nNUMBER: "$3}' /etc/passwd #按照自己想要的格式与内容输出 USER_NAME: root NUMBER: 0 USER_NAME: daemon NUMBER: 1 USER_NAME: bin NUMBER: 2 USER_NAME: sys NUMBER: 3 USER_NAME: sync NUMBER: 4 USER_NAME: games NUMBER: 5
示例文件内容 $ cat inventory hammers 5 7.99 drills 2 29.99 punches 7 3.59 drifts 2 4.09 bits 55 1.19 saws 123 14.99 nails 800 .19 screws 80 .29 brads 100 .24
$ awk 'BEGIN {print "ITEM\tQUANTITY\tPRICE\tTOTAL"} {x=x+($2*$3)} {print $1"\t"$2"\t\t"$3"\t"$2*$3} END {print "Total Value of Inventory: " x}' inventory ITEM QUANTITY PRICE TOTAL #BEGIN关键字 hammers 5 7.99 39.95 drills 2 29.99 59.98 punches 7 3.59 25.13 drifts 2 4.09 8.18 bits 55 1.19 65.45 saws 123 14.99 1843.77 nails 800 .19 152 screws 80 .29 23.2 brads 100 .24 24 Total Value of Inventory: 2241.66 #END关键字 x最后的值
awk本身是一个编程语言,另外还支持if语句,循环语句;用法类似C语言的编程