awk命令

Linux之awk命令

1.awk简介

功能:awk就是把文件逐行的的读入,以空格为默认分隔符将每行切片,切片的部分再进行各种分析处理
         
工作模式:
1、行工作模式,读入一行文件,存在“$0”里
2、使用内置变量FS(字段分隔符)分割一行,存到$1-$100
3、输出时也是用内置变量OFS,输出该行

与sed主要异同:
相同点:
1.他们的语法基本相同
2.他们都是流编辑器,工作方式都是读入一行,处理动作,输出结果
3.他们都使用正则表达式作模式匹配
4.他们都允许使用脚本

不同点:
1.sed主要处理行,awk主要处理列
2.sed处理动作必须与文件内容相关,awk处理动作可以与文件内空无关,并且awk的动作要用{}括起来.

小结:awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得由为强大。

2.awk语法

awk -F|-f|-v 'BEGIN{ } / / {comand1;comand2} END{ }' file
-F 定义列分隔符
-f 指定调用脚本
-v 定义变量
' '引用代码块,awk执行语句必须包含在内
BEGIN{ } 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
{ } 命令代码块,包含一条或多条命令
// 用来定义需要匹配的模式(字符串或者正则表达式),对满足匹配模式的行进行上条代码块的操作
END{ }  结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

3.特殊要点

$0          表示整个当前行
$1          每行第一个字段
NF          字段数量变量
NR          每行的记录号,多文件记录递增
FS          BEGIN时定义分隔符
RS          输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
FNR         与NR类似,不过多文件记录不递增,每个文件都从1开始
OFS         输出字段分隔符, 默认也是空格,可以改为制表符等
ORS         输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
FILENAME    文件名
\t          制表符
\n          换行符
~           匹配,与==相比不是精确比较
!~          不匹配,不精确比较
==          等于,必须全部相等,精确比较
!=          不等于,精确比较
&&         逻辑与
||          逻辑或
+           匹配时表示1个或1个以上
/[0-9][0-9]+/    两个或两个以上数字
/[0-9][0-9]*/    一个或一个以上数字
-F'[:#/]'        定义三个分隔符

4.awk输出

4.1 print

awk -F ":"  '{print $1"\t"$3}' /etc/passwd
awk -F ":"  '{print $1,$3}' OFS="\t" /etc/passwd
awk -F ":"  '/root/{print $1,$3}' OFS="\t" /etc/passwd

print要点

各个输出字段之间用逗号分隔,而输出时默认以空白分隔
print后面如果不指定字段,那么就会打印一整行
print输出时默认是有换行符的

4.2 printf

printf —— 可以格式化输出,默认没有换行

使用格式:printf format item1,item2,... ...,itemn
format的指示符都是以%开头的,后面跟一个字符,如:
%s:表示是字符串             string
%d:表示十进制整数
%f:表示浮点数,也就是小数   float
%%:表示%本身
%x:表示十六进制数
%o:表示八进制数
%c :表示字符
N(数字) 表示显示宽度 %5d   注意:指定字段显示宽度时>=该字段最长的长度
-:左对齐,默认是右对齐     %-5s (向左五个字符)
%5.2f:其中5表示总的显示宽度(整数位+小数位),2表示小数的位数
%-5.2f
%.2f:整数位全部保留,小数位保留两位

示例

echo 12.34 15.78 > a.txt
awk -F" " '{printf "%d\n",$1}' a.txt  #%d直接取整,不四舍五入
12
awk -F ":" '{printf $3"\t"$4"\n"}' /etc/passwd  # \t  制表符 \n 换行    都需要用" "来区分
awk -F ":" '{printf "%s%s\n",$1,$3}' /etc/passwd  #%s%    printf 后面需要加\n    %s%s 默认没有输出分隔符
awk -F ":" '{printf "%d%d\n",$3,$4}' /etc/passwd  #%d%d 表示以整数和整数的格式显示
awk -F ":" '{printf "%10s%d\n",$3,$4}' /etc/passwd #%10s%d 表示以字符串和整数的格式向右移动10个字段
awk -F ":" '{printf "%-d%10d\n",$3,$4}' /etc/passwd #-:左对齐
awk '{printf "%.3f\n",$1}' a.txt   #%.3f 表示整数位保留,小数位保留3位

5.awk属组

数组:array 关联数组:因为awk数组的下标可以是数值,也可以是字符串 
数组的定义:数组名[下标]=值
awk数组用于:收集信息、统计总数、计算次数、记录模式出现的次数等等   awk数组既可以先定义再使用,也可以用到时候再定义。
数组的遍历
特殊的for循环来遍历数组
语法:for (下标 in 数组名){ print 数组名[下标]}

示例1

定义数组,并且打印数组元素
awk 'BEGIN{a[0]="xiaohong";a[1]="xiaolan";print a[0]}'
awk 'BEGIN{a[0]="xiaohong";a[1]="xiaolan";print a[1]}'

打印出所有元素的下标
awk 'BEGIN{a[0]="xiaohong";a[1]="xiaolan";for (i in a)print i;}'

将/etc/passwd/里边的第一类定义成数组
awk -F":" '{{a[NR]=$1;}{print NR,a[NR];}}' /etc/passwd

示例2

[root@docker ~]# cat a.txt 
192.168.3.1
192.168.3.2
192.168.3.3
192.168.3.4
192.168.3.5
192.168.3.6
192.168.3.7
192.168.3.1
192.168.3.2
192.168.3.3
192.168.3.3
192.168.3.3
192.168.3.2
192.168.3.3
192.168.3.6
192.168.3.6
192.168.3.3
192.168.3.2
192.168.3.2

利用数组统计每一个IP的访问量
awk '{a[$1]++} END {for(b in a) print a[b],b}' a.txt | sort -nr
6 192.168.3.3
5 192.168.3.2
3 192.168.3.6
2 192.168.3.1
1 192.168.3.7
1 192.168.3.5
1 192.168.3.4

Awk在读取第一行的时候,会读取这个数组,此时的数组是这样的:a[192.168.3.1]++。
此时a[192.168.3.1]的值是未定义的。但是由于后边有运算符号++。Awk会将数字0自动赋值给a[192.168.3.1]。然后在做++运算
此时a[192.168.3.1]做++ ,也就是0+1得到的值为1
那么在读第二个192.168.3.1时,此时a[192.168.3.1]的值已经经过上次运算为1.此时在做一次运算。也就是1+1 现在a[192.168.3.1]的值为2。
总结,最后的值是多少,也就意味着,192.168.3.1运算了多少次,也意味着192.168.3.1出现了多少次。

6.awk变量

FS  字段分隔符,默认是空白
RS  记录分隔符,即行的分隔符
OFS 输出字段分隔符
ORS 输出记录分隔符
NF  当前行的字段数(number field 字段号) 
$NF:当前行最后一个字段的值
$(NF-1) 当前行倒数第二个字段的值
NR  number record 记录行号
substr 截取指定的字符串
gsub   替换指定字符串 

示例1

FS设置域分隔符 等于-F
[root@docker ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd

OFS 输出域分隔符
[root@docker ~]# cat a.txt 
192.168.3.1 192.168.3.2
[root@docker ~]# awk 'BEGIN{OFS=","}{print $1,$2}' a.txt 
192.168.3.1,192.168.3.2
注意:这种情况需要多列,单列是不行的

NF 打印每行内容有多少列
awk -F":" '{print NF}' /etc/passwd

NR 已读的行记录数
awk '{print NR}' /etc/passwd

示例2

ORS 输出记录分隔符
注明:awk规定,对于文本文件,默认情况下,一条记录对应一行,即记录之间的默认分隔符是换行符;而一条记录又可以分为多个字段,默认字段分隔符为空格。
cat a.txt 
192.168.3.1 
192.168.3.2 
awk 'BEGIN{ORS=","}{print $0}' a.txt 
192.168.3.1 ,192.168.3.2 ,

示例3

substr($n,n)  打印指定的列,并且从指定的第n个字符开始打印
substr($n,n,m)  打印指定的列,并且从指定的第n个字符开始打印,到m个字符停止
awk 'BEGIN{FS=":"}{if(NR==1){print substr($NF,1)}}' /etc/passwd
awk 'BEGIN{FS=":"}{if(NR==1){print substr($NF,2)}}' /etc/passwd
awk 'BEGIN{FS=":"}{if(NR==1){print substr($NF,3)}}' /etc/passwd
ifconfig eth0 |awk '{if(NR==2){print substr($2,1,15)}}'

示例4

将第一行的每个字符后面加一个空格
awk 'BEGIN{ORS=" "}{if(NR==1){for(i=1;i<=length();i++){print substr($0,i,1)}print "\n"}}' /etc/passwd
r o o t : x : 0 : 0 : r o o t : / r o o t : / b i n / b a s h

正则匹配替换多个空格为“#”
awk 'BEGIN{array="a b c d"; gsub(/ +/, "#", array); print array;}'
a#b#c#d

7.awk操作符

赋值运算符
= += -= *= /= %= ^=	赋值语句

逻辑运算符
||	逻辑或
&&	逻辑与

正则运算符
~ ~!  匹配正则表达式和不匹配正则表达式

关系运算符
< <= > >= != ==	关系运算符

算术运算符
+ -	加,减
* / &	乘,除与求余
+ - !	一元加,减和逻辑非
^ ***	求幂
++ --	增加或减少,作为前缀或后缀

其它运算符
$	字段引用
空格	字符串连接符
? :	C条件表达式
in	数组中是否存在某键值

*awk赋值运算符*

awk 'BEGIN{a=5; a+=5; print a; a*=2; print a; a^=2; print a; a%=2; print a;}'
10
20
400
0

*awk逻辑运算符*

awk 'BEGIN{a=1; b=2; print (a>0), (b<0), (a>5 && b<=2),(a>5 || b<=2);}'
1 0 0 1

*awk正则运算符*

awk 'BEGIN{a="100testa";if(a ~ /^100*/){print "ok";}}'
ok

*awk关系运算符*

awk 'BEGIN{a=11; if(a >= 9){print "ok";}}' 
ok

awk 'BEGIN{a="11"; if(a >= 9){print "ok";} else{print "no";}}' 
no

*awk算术运算符*

awk 'BEGIN{a="12"; print a, a++,++a; print a+2, a*2, a^2, !a}'
12 12 14
16 28 196 0

*其它运算符*

awk 'BEGIN{a="b"; arr[0]="b"; arr["b"]="c"; print (a in arr); print arr[a];}'
1
c

awk 'BEGIN{a="b"; print a=="b" ? "ok" : "err";}'
ok

echo "a b c d" | awk '{print $1, $3}'
a c

awk 'BEGIN{arr="a b c d"; gsub(/ +/, "#", arr); print arr;}'
a#b#c#d
注明:则匹配替换多个空格为“#”

8.awk正则表达式

字符功能
+指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:awk ‘/smith+ern/’ testfile将包含字符 smit,后跟一个或多个 h 字符,并以字符ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是:smithern, harry smithhern, anne
?指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:awk ‘/smith?/’ testfile将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是:smith, alan smithern, harry smithhern, anne smitters, alexis
|指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:awk ‘/allen | alan /’ testfile将包含字符串 allenalan 的所有记录打印至标准输出。此示例中的输出是:smiley, allen smith, alan
( )在正则表达式中将字符串组合在一起。命令行:awk ‘/a(ll)?(nn)?e/’ testfile将具有字符串 aealleanneallnne 的所有记录打印至标准输出。此示例中的输出是:smiley, allen smithhern, anne
{m}指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:awk ‘/l{2}/’ testfile打印至标准输出smiley, allen
{m,}指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:awk ‘/t{2,}/’ testfile打印至标准输出:smitters, alexis
{m, n}指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m<= n),则字符串匹配。命令行:awk ‘/er{1, 2}/’ testfile打印至标准输出:smithern, harry smithern, anne smitters, alexis
[String]指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:awk ‘/sm[a-h]/’ testfile将具有 sm 后跟以字母顺序从 ah 排列的任何字符的所有记录打印至标准输出。此示例的输出是:smawley, andy
[^ String]在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:awk ‘/sm[^a-h]/’ testfile打印至标准输出:smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis
,!表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:awk ‘$1 ~ /n/’ testfile将第一个字段包含字符 n 的所有记录打印至标准输出。此示例中的输出是:smithern, harry smithhern, anne
^指定字段或记录的开头。命令行:awk ‘$2 ~ /^h/’ testfile将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是:smithern, harry
$指定字段或记录的末尾。命令行:awk ‘ 2   / y 2 ~ /y 2 /y/’ testfile将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是:smawley, andy smithern, harry
. (句号)表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:awk ‘/a…e/’ testfile将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:smawley, andy smiley, allen smithhern, anne
*(星号)表示零个或更多的任意字符。命令行:awk ‘/a.*e/’ testfile将具有以零个或更多字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:smawley, andy smiley, allen smithhern, anne smitters, alexis
\ (反斜杠)转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:/a///将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。

示例

统计系统中每种shell的用户有几人
awk -F: '{a[$NF]++}END{for(b in a){print b,a[b]}}'  /etc/passwd
/bin/sync 1
/bin/bash 5
/bin/sh 1
/sbin/nologin 31
/sbin/halt 1
/sbin/shutdown 1
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东城绝神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值