awk命令

awk文本处理工具原理及使用

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势 。

1.常用命令选项:

命令意义
-F指定输入分隔符,可以是字符串或正则表达式,如-F:
-vvar=value 赋值一个用户定义变量,将外部变量传递给awk(每定义一个变量一个参数-v)
-fscriptfile 从脚本文件中读取awk命令
-vOFS=”\t” OFS变量表示输出分隔符(每定义一个变量一个参数-v

2.模式和操作:

awk脚本是由模式和操作来组成的
模式可以是以下任意一个:
①/正则表达式/: 使用通配符的扩展集,在”/” “/”这两根斜线之间的是正则表达式
②关系表达式: 使用运算符进行操作,可以是字符串或数字的比较测试
③模式匹配表达式: 用运算符 ~(匹配)和 ~!(不匹配)
④BEGIN语句块、pattern语句块、END语句块

操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是 :
①变量或数组赋值
②输出命令
③内置函数
④控制流语句

3.基本结构:

awk ‘BEGIN{ print “start” } pattern{ commands } END{ print “end” }’ file
一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。
任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中
awk ‘BEGIN{ i=0 } { i++ } END{ print i }’ filename
awk “BEGIN{ i=0 } { i++ } END{ print i }” filename

#内置变量 
[root@localhost ~]# more filename 
aa 100
bb 353

[root@localhost ~]# awk '{ print $NF }' filename
100
353
#打印出一行中的最后一个字段;$(NF-1)

[root@localhost ~]# awk '{ print NF }' filename
2
2
 #总字段数,也可组合使用

[root@localhost ~]# awk '{ printf("%s^%s\n",$1,$2) }' filename   
aa^100
bb^353

[root@localhost ~]# awk 'END{ print NR }' filename
2
 #统计文件中的行数,命令只用了END语句块,在读入每一行的时,awk会将NR更新为对应的行号,当到最后一行NR的值就是最后一行的行号,所以END语句块中的NR就是文件的行数

[root@localhost ~]# seq 100 | awk 'BEGIN{sum=0} {sum+=$1} END{print "总和:"sum}' 
总和:5050
#一个每一行中第一个字段值累加

#外部变量传递
[root@localhost ~]# echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
10000

[root@localhost ~]# var1="aaa"
[root@localhost ~]# var2="bbb"
[root@localhost ~]# echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
aaa bbb

[root@localhost ~]# echo | awk '{print ENVIRON["PATH"]} ' 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

#awk运算与判断
#+ - 加、减
#* / & 乘、除、求余
#+ - ! 一元加、减、逻辑非
#^ ** 求幂
#++ -- 增加或减少,作为前缀或后缀
[root@localhost ~]# awk 'BEGIN{ a=1; print a++,++a;}'
1 3
#赋值运算符
#= += -= *= /= %= ^= **= 赋值语句
#a+=5; 等价于:a=a+5; 其它同类
#逻辑运算符
#|| 逻辑或
#&& 逻辑与
[root@localhost ~]# awk 'BEGIN{a=1;b=2; print (a>5 && b<=2),(a>5 || b<=2);}'
0 1

#正则运算符
#~ ~! 匹配正则表达式和不匹配正则表达式
[root@localhost ~]# awk 'BEGIN {a="100testa"; if(a ~ /^100*/) {print "ok";}}'
ok

#关系运算符
#< <= > >= != == 关系运算符
[root@localhost ~]# awk 'BEGIN{a=11; if(a >= 9) {print "ok";}}'
ok

#其它运算符
#$ 字段引用
#空格 字符串连接符
#a>b?y:n 三目运算条件表达式
#in 数组中是否存在某键值
[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err";}'
ok
[root@localhost ~]# awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print (a in arr);}'
1
[root@localhost ~]# awk 'BEGIN{a="b";arr[0]="b";arr[1]="c";print (a in arr);}'
0
#高级输入输出
[root@localhost ~]# more filename 
aa 100
bb 353
cc 234
total 1000
[root@localhost ~]# awk '{if($1=="total"){next};print }' filename
aa 100
bb 353
cc 234
[root@localhost ~]# 
 #awk中next语句,相当于其他编程语言的continue
[root@localhost ~]# more text.txt
web01[192.168.2.100]
httpd ok
tomcat ok
sendmail ok
[root@localhost ~]# awk '/^web/{T=$0;next;}{print T":"$0;}' text.txt  
web01[192.168.2.100]:httpd ok
web01[192.168.2.100]:tomcat ok
web01[192.168.2.100]:sendmail ok
 #分析发现需要将包含有“web”行进行跳过,然后需要将内容与下面行合并为一行
#简单地读取一条记录
[root@localhost ~]# awk 'BEGIN{ "date" | getline out; print out }' test
Mon Nov  5 16:57:31 CST 2018

#输出到一个文件 输出重定向 
[root@localhost ~]# more file1
hello linux!
[root@localhost ~]# echo | awk '{printf("hello word!") > "file1"}'   覆盖原内容
hello word!
[root@localhost ~]# echo | awk '{printf("hello word!") >> "file1"}'  追加到原内容后
[root@localhost ~]# more file1
hello linux!hello word!

#设置字段定界符
[root@localhost ~]# awk -F: '{ print $NF }' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
...(省略后面内容)
[root@localhost ~]# awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
...(省略后面内容)
[root@localhost ~]# awk 'BEGIN{FS=":"; OFS="-->"} {print $1,$3}' /etc/passwd 
root-->0
bin-->1
daemon-->2
...(省略后面内容)
#在BEGIN语句块中则可以用OFS=“定界符”设置输出字段的定界符

测试:

#名称,电话,过去三个月捐款数
Mike Harrington:[510] 548-1278:250:100:175
Christian Dobbins:[408] 538-2358:155:90:201
Susan Dalsass:[206] 654-6279:250:60:50
Archie McNichol:[206] 548-1348:250:100:175
Jody Savage:[206] 548-1278:15:188:150
Guy Quigley:[916] 343-6410:250:100:175
Dan Savage:[406] 298-7744:450:300:275
Nancy McNeil:[206] 548-1278:250:80:75
John Goldenrod:[916] 348-4278:250:100:175
Chet Main:[510] 548-5258:50:95:135
Tom Savage:[408] 926-3456:250:168:200
Elizabeth Stachelin:[916] 440-1763:175:75:300

1.显示所有电话号码

[root@localhost ~]# awk -F: '{print $2}' awk_text 
[510] 548-1278
[408] 538-2358
[206] 654-6279
[206] 548-1348
[206] 548-1278
...(省略后面内容)

2.显示Dan的电话号码

[root@localhost ~]# awk -F: '/^Dan/{print $2}' awk_text 
[406] 298-7744

3.显示Susan的名字和电话号码

[root@localhost ~]# awk -F: '/^Susan/{print $1 ,$2}' awk_text 
Susan Dalsass [206] 654-6279

4.显示所有以D开头的姓

[root@localhost ~]# awk -F: '{print $1}' awk_text|awk '{print $2}'  | awk '/^D/'  
Dobbins
Dalsass

5.显示所有以一个C或E开头的名

[root@localhost ~]# awk -F: '{print $1}' awk_text | awk '{print $1}' | awk '/^[CE]/'
Christian
Chet
Elizabeth
[root@localhost ~]# awk -F: '{print $1}' awk_txet | awk '/^[CE]/{print $1}'
Christian
Chet
Elizabeth
[root@localhost ~]#

6.显示所有只有四个字符的名,这里可以使用length函数,举例: length(1)==10 1字符为10

[root@localhost ~]# awk -F: '{print $1}' awk_text | awk '{if(length($1) == 4)print $1}'
Mike
Jody
John
Chet

7.显示所有区号为916的人名

[root@localhost ~]# awk -F: '/916/{print $1}' awk_text 
Guy Quigley
John Goldenrod
Elizabeth Stachelin

8.显示Mike的捐款.显示每个值时都有以$开头.如$250$100$175

[root@localhost ~]# awk -F: '/^Mike/{print "$"$3"$"$4"$"$5}' awk_text 
$250$100$175

9.显示姓,其后跟一个逗号和名

[root@localhost ~]# awk -F: '{print $1}' awk_text | awk '{print $2,",",$1}'     
Harrington , Mike
Dobbins , Christian
Dalsass , Susan
McNichol , Archie
Savage , Jody
...(省略后面内容)
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值