Linux:文件管理:awk;awk 命令

处理文本文件,进行文本分析

REFERENCE:

The Syntax of awk

awk [选项参数] 'script' var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)

选项参数

  • -F fs | --fiel-separator fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如`-F:。

  • -v var=value | --asign var=value
    赋值一个用户定义变量。

    awk -F: -v i=5 '{ print $3,$(i-2) }' /etc/passwd
    0 0
    1 1
    2 2
    
  • -f scripfile | --file scriptfile
    从脚本文件中读取awk命令。

    awk -f xxx.awk /etc/passwd
    
  • -mf nnn & -mr nnn
    对nnn值设置内在限制,-mf 选项限制分配给nnn的最大块数目;-mr 选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

  • -W compact | --compat, -W traditional | --traditional
    在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。

  • -W copyleft | --copyleft, -W copyright | --copyright
    打印简短的版权信息。

  • -W help | --help, -W usage | --usage
    打印全部awk选项和每个选项的简短说明。

  • -W lint | --lint
    打印不能向传统 unix 平台移植的结构的警告。

  • -W lint-old | --lint-old
    打印关于不能向传统unix平台移植的结构的警告。

  • -W posix
    打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当 fs 是一个空格时,将新行作为一个域分隔符;操作符 ****= 不能代替 ^^=;fflush无效。

  • -W re-interval | --re-inerval
    允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式 [[:alpha:]]。

  • -W source program-text | --source program-text
    使用 program-text 作为源代码,可与 -f 命令混用。

  • -W version | --version
    打印 bug 报告信息的版本。

AWK 原理

只查看 passwd 文件内,第 20 到 30 行的内容

awk '{ if( NR>=20 && NR<=30 ){print $0} }' /etc/passwd
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin

已知 passwd 文件内容,从中过滤出用户名 root 和命令解析器 /bin/bash,最后输出 root /bin/bash

awk -F ':' '{ if( NR==1 )print $1" "$7 }' /etc/passwd
root /bin/bash

BEGIN/END 模块

统计 /etc/passwd 的账户人数

awk '{count++} END{print "[END] The number of users is ",count}' /etc/passwd
[END] The number of users is  21

count 是自定义变量,这里没有初始化 count,虽然默认是 0,但最稳妥的做法还是初始化

awk 'BEGIN{count=0} {count++} END{print "[END] The number of users is ",count}' /etc/passwd
[END] The number of users is  21

AWK 运算符

DescriptionOperational Character
赋值= += -= *= /= %= ^= **=
逻辑|| &&
正则~ 匹配正则表达式; !~ 不匹配正则表达式
关系< > <= >= != ==
算术+ - * / & 取余;^ *** 求幂;++ –
其他In 数组中是否存在某键值;$ 字段引用
赋值
awk 'BEGIN{ a=5;a+=5;print a }'
10
逻辑
awk 'BEGIN{ a=0;print ( a>-1||a<0 , a>-1&&a<0 ) }'
1 0
正则
awk 'BEGIN{ str="192,168,10,222";if( str~10 ){print "true"} }'
true
echo | awk 'BEGIN{ str="192,168,10,222" } str~10 {print "true"}'
true
关系
awk 'BEGIN{ a=0;print (a<0,a==0,a>0) }'
0 1 0

< > 可以比较字符串,也可比较数值。

awk 'BEGIN{ a="11";if(a>=9){print "true"} }' # 无输出,比较的 ASCII 码顺序
awk 'BEGIN{ a=11;if(a>=9){print "true"} }'
true
算术

经算数运算符操作,操作数自动转为数值,所有非数值都变为0

awk 'BEGIN{ a="b";b="2b";print a,b,a++,b++ }'
b 2b 0 2
其他:三目运算
awk 'BEGIN{ a="b";print a=="b"?1:0 }'
1

AWK 内置变量

VariateDescriptionDefault
$0当前记录
$1~$n当前记录的第 n 个字段
FSField Separator输入字段分隔符空格
RSRecord Separator输入记录分隔符\t
NFNumber Of Field当前记录中的字段个数;总列数
NRNumber Of Record当前记录数;行号
OFSOutput Field Separator输出字段分隔符空格
ORSOutput Record Separator输出记录分割符\t
FS 字段分割符

换行

awk 'BEGIN{ FS="\t+" }{ print $0 }' xxx.md # 一个 or 多个 Tab 分割符

空格

awk -F [[:space:]+] '{ print $0 }' xxx.md # 一个 or 多个空格

多个分隔符

awk -F '[ :/]' 'BEGIN{ OFS="\t" }{ print $2,$3,$9 }' /etc/passwd
x	0	bin
x	1	sbin
x	2	sbin
RS 记录分隔符 ⭐️
awk 'BEGIN{ RS="" }{ print $0 }' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
·················
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
awk 'BEGIN{ RS="" }{ print $1 }' /etc/passwd
root:x:0:0:root:/root:/bin/bash
awk 'BEGIN{ RS="" }{ print $2 }' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
NF 字段数量
awk -F "/" 'NF==5{print $0}' /etc/passwd # 按 / 分割,字段数量为 5 的打印
adm:x:3:4:adm:/var/adm:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
NR 记录数量
awk 'NR==1{print $0}' /etc/passwd # NR==1,取第一行数据
root:x:0:0:root:/root:/bin/bash
OFS 输出字段分隔符

ORS 输出记录分隔符

IGNORECASE 忽略大小写
awk 'BEGIN{ IGNORECASE=1 } /user/' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin

AWK 正则表达

CharacterFunctionSamplesInterpretation
^行首定位符/^root/匹配所有以 root 开头的行
$行尾定位符/root$/匹配所有以 root 结尾的行
.匹配 1 个字符/r..t/匹配 r 为头,t 为尾的四字符串
*匹配 [0,+∞) 个前导字符/roo*t/
+匹配 [1,+∞) 个前导字符/ro+t/
?匹配 [0,1] 个前导字符/r?oot/
[]匹配 [] 内的任意一个字符/^[abc]/匹配以 a、b、c 开头的行
[^]匹配不属于 [^] 内的字符/^[^ab]/匹配不以 a、b 开头的行
()子表达式组合/(root)+/[1,+∞) 个 root 组合
|或者/(root)|(user)/匹配 root 或 user 的行
\转义字符/a\/匹配 a/
~匹配$1~/root/匹配第一个字段包含字符 root 的行
!~不匹配$1!~/root/
x{m}x 重复 m 次/[rot]{4}/匹配四个连续字符全由 rot 组成的行
x{m,}x 重复 m 次及以上
x{m,n}x 重复 m~n 次
规则表达式
awk '/REG/{ACTION}' FILE # /REG/ 为正则表达式,可以将 $0 中,满足条件的的记录送到 ACTION 进行处理
awk '/root/{print $0}' /etc/passwd # 匹配包含 root 的行
布尔表达式
awk 'BOOLEAN{ACTION}' FILE # 仅当 BOOLEAN 值为 TRUE 时,awk 才执行 ACTION
awk -F: '$1=="root"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

条件循环

if

if($1=="root"){
  print $0
}

while


do while

count=1
do{
  print $1
} while( count !=1 )

for

for( i=1;i<10;i++){
  print $1
}

数组

用 awk 中查看服务器连接状态并汇总

netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}'
ESTABLISHED 1
LISTEN 20

统计 web 日志访问流量,要求输出访问次数,请求页面或图片,每个请求的总大小,总访问流量的大小汇总

awk '{a[$7]+=$10;++b[$7];total+=$10}END{for(x in a)print b[x],x,a[x]|"sort -rn -k1";print "total size is :"total}' /app/log/access_log
total size is :172230
21 /icons/poweredby.png 83076
14 / 70546
8 /icons/apache_pb.gif 18608
a[$7]+=$10 表示以第 7 列为下标的数组( $10 列为$7 列的大小),把他们大小累加得到 $7 每次访问的大小,后面的 for 循环有个取巧的地方, a 和 b 数组的下标相同,所以一条 for 语句足矣

字符串函数

FunctionDescription
gsub( Ere,Repl,[In] )
sub( Ere,Repl,[In] )
index( String1,String2 )
length[( String )]字符串长度
blength[( String )]字符串长度,单位字节
substr( String,M,[N] )字符串截取
match( String,Ere )
split( String,A,[Ere] )
tolower( String )
toupper( String )
sprintf( Format,Expr,Expr,... )
gsub 替换
awk 'BEGIN{ str="abc123abc";gsub(/[0-9]+/,"!",str);print str }'
abc!abc

在 str 中查找满足正则表达式的子串,用 ! 替换,并返回替换后的值给 str

index 查找
awk 'BEGIN{ str="abc123abc";print index(str,"abc")?"true":"false" }'
true # 查找到则返回非零
match 匹配查找
awk 'BEGIN{ str="abc123abc";print match(str,/[0-9]+/) }'
4
substr 截取
awk 'BEGIN{ str="abc123abc";print substr(str,4,6) }'
123abc

Exercise

格式化输出

awk -F: '{printf "%-8s %-10s\n",$1,$6 }' /etc/passwd
root     /root     
bin      /bin      
daemon   /sbin     

运算符:过滤第三列小于 3 的行

awk -F: '$3<3' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

计算文件大小

ls -l | awk '{ sum+=$5 } END{ print sum }'
1535

从文件中找出长度大于 60 的行

awk 'length>60' /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

打印九九乘法表

seq 9 | sed 'H;g' | awk -v RS='' '{ for(i=1;i<=NF;i++)printf("%dx%d=%d%s",i,NR,i*NR,i==NR?"\n":"\t") }'
1x1=1
1x2=2	2x2=4
1x3=3	2x3=6	3x3=9
1x4=4	2x4=8	3x4=12	4x4=16
1x5=5	2x5=10	3x5=15	4x5=20	5x5=25
1x6=6	2x6=12	3x6=18	4x6=24	5x6=30	6x6=36
1x7=7	2x7=14	3x7=21	4x7=28	5x7=35	6x7=42	7x7=49
1x8=8	2x8=16	3x8=24	4x8=32	5x8=40	6x8=48	7x8=56	8x8=64
1x9=9	2x9=18	3x9=27	4x9=36	5x9=45	6x9=54	7x9=63	8x9=72	9x9=81
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值