linux | 深入学习awk命令,了解它强大而又丰富的功能

本文详细介绍了awk命令的语法、执行流程,以及其运算符、内建变量和高级功能,包括数组使用、正则匹配、IF语句等。通过实际案例演示如何利用awk处理passwd文件和csv文件,提升文本数据分析能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

awk命令的完整语法

awk的命令的执行过程

选项

awk支持的运算符

 常用内建变量

print & $0

忽略大小写

模式取反

awk脚本

-F指定分隔符

//匹配代码块

IF语句

AWK 数组

练习


AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

awk命令的完整语法

awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file

 [-F|-f|-v]   大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value

'  '          引用代码块

BEGIN   初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符

//           匹配代码块,可以是字符串或正则表达式

{}           命令代码块,包含一条或多条命令

;          多条命令使用分号分隔

END      结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

awk的命令的执行过程

  • 1、通过关键字 BEGIN 执行 BEGIN 块的内容,即 BEGIN 后花括号 {} 的内容。
  • 2、完成 BEGIN 块的执行,开始执行body块。
  • 3、读入有 \n 换行符分割的记录。
  • 4、将记录按指定的域分隔符划分域,填充域,$0 则表示所有域(即一行内容),$1 表示第一个域,$n 表示第 n 个域。
  • 5、依次执行各 BODY 块,pattern 部分匹配该行内容成功后,才会执行 awk-commands 的内容。
  • 6、循环读取并执行各行直到文件结束,完成body块执行。
  • 7、开始 END 块执行,END 块可以输出最终结果。

选项

  • -F fs or  --field-separator fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
  • -v var=value or --asign var=value
    赋值一个用户定义变量。
  • -f scripfile or --file scriptfile
    从脚本文件中读取awk命令。
  • -mf nnn and -mr nnn
    对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
  • -W compact or --compat, -W traditional or --traditional
    在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
  • -W copyleft or --copyleft, -W copyright or --copyright
    打印简短的版权信息。
  • -W help or --help, -W usage or --usage
    打印全部awk选项和每个选项的简短说明。
  • -W lint or --lint
    打印不能向传统unix平台移植的结构的警告。
  • -W lint-old or --lint-old
    打印关于不能向传统unix平台移植的结构的警告。
  • -W posix
    打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
  • -W re-interval or --re-inerval
    允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
  • -W source program-text or --source program-text
    使用program-text作为源代码,可与-f命令混用。
  • -W version or --version
    打印bug报告信息的版本。

awk支持的运算符

运算符描述
= += -= *= /= %= ^= **=赋值
||逻辑或
&&逻辑与
~ 和 !~匹配正则表达式和不匹配正则表达式(模糊匹配)
< <= > >= != ==关系运算符
空格连接
+ -加,减
* / %乘,除与求余
+ - !一元加,减和逻辑非
^ ***求幂
++ --增加或减少,作为前缀或后缀
$字段引用
in

数组成员

==和!=精准匹配和精准不匹配

 常用内建变量

变量描述
$n当前记录的第n个字段,字段间由FS分隔
$0完整的输入记录
FILENAME当前文件名
FNR各文件分别计数的行号
FS字段分隔符(默认是任何空格),BEGIN命令时使用
NF一条记录的字段的数目
NR已经读出的记录数,就是行号,从1开始
OFS输出字段分隔符,默认值为任何空格
ORS输出记录分隔符(默认值是一个换行符)即文本是按一行一行输出
RS记录分隔符(默认是一个换行符)即文本是按一行一行输入
IGNORECASE如果为真,则进行忽略大小写的匹配

+            匹配时表示1个或1个以上

/[0-9][0-9]+/   两个或两个以上数字

/[0-9][0-9]*/    一个或一个以上数字

注意:

-F'[:#/]'   定义三个分隔符

-F指定分隔符时,-F与指定的分隔符之间加不加空格都行

print & $0

print 是awk打印指定内容的主要命令

1.输出/etc/passwd文件中所有的内容

awk '{print}'  /etc/passwd   
awk '{print $0}'  /etc/passwd  
awk '/li/' /etc/passwd  #默认命令即为输出匹配的整行

2.不输出passwd的内容,而是输出相同个数的空行,进一步解释了awk是一行一行处理文本

awk '{print " "}' /etc/passwd         

   3.输出相同个数的a行,一行只有一个a字母                               

awk '{print "a"}'   /etc/passwd     

4.将每一行的前二个字段,分行输出,进一步理解一行一行处理文本

awk -F: '{print $1; print $2}'   /etc/passwd 

5.输出字段1,3,6,以制表符作为分隔符统计一个文件中的空行

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

 6.统计test.txt文件中的空行数量

awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test.txt

7.统计当前文件夹下所有文件和文件夹大小的和,即当前文件夹的大小

 ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}' 

8.使用正则,字符串匹配,输出第二列包含 "th",并打印第二列与第四列

awk '$2 ~ /th/ {print $2,$4}' log.txt

 ~ 表示模式开始。// 中是模式

忽略大小写

awk 'BEGIN{IGNORECASE=1} /this/' log.txt

模式取反

awk -F: '$1 !/li/ {print $2,$4}' /etc/passwd
awk -F: '$1 !~ /li/ {print $2,$4}' /etc/passwd

awk脚本

关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。

  • BEGIN{ 这里面放的是执行前的语句 }
  • END {这里面放的是处理完所有的行后要执行的语句 }
  • {这里面放的是处理每一行时要执行的语句}

假设有这么一个文件(学生成绩表):

$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

我们的 awk 脚本如下:

$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
 
    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

我们来看一下执行结果:

$ awk -f cal.awk score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
---------------------------------------------
  TOTAL:       319      393      350
AVERAGE:     63.80    78.60    70.00

-F指定分隔符

awk默认分隔符为任意空格,将一行文本分割成多个字段

awk -F":" '{print $1}'  /etc/passwd

#//$1与$3相连输出,不分隔
awk -F":" '{print $1 $3}'  /etc/passwd 
                      
#//多了一个逗号,$1与$3使用空格分隔
awk -F":" '{print $1,$3}'  /etc/passwd
                       
#//$1与$3之间手动添加空格分隔
awk -F":" '{print $1 " " $3}'  /etc/passwd  

#//自定义输出                  
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd       

#//显示每行有多少字段
awk -F: '{print NF}' /etc/passwd                                

#//将每行第NF个字段的值打印出来
awk -F: '{print $NF}' /etc/passwd                              

#//显示只有4个字段的行
awk -F: 'NF==4 {print }' /etc/passwd   

#//显示每行字段数量大于2的行                    
awk -F: 'NF>2{print $0}' /etc/passwd                       

#//输出每行的行号
awk '{print NR,$0}' /etc/passwd                                 

#//依次打印行号,字段数,最后字段值,制表符,每行内容
awk -F: '{print NR,NF,$NF,"\t",$0}' /etc/passwd   

#//显示第5行
awk -F: 'NR==5{print}'  /etc/passwd

#//显示第5行和第6行                         
awk -F: 'NR==5 || NR==6{print}'  /etc/passwd       

#//不显示第一行
route -n|awk 'NR!=1{print}'                                       

//匹配代码块

//纯字符匹配   !//纯字符不匹配   ~//字段值匹配    !~//字段值不匹配   ~/a1|a2/字段值匹配a1或a2

awk '/mysql/' /etc/passwd

awk '/mysql/{print }' /etc/passwd

awk '/mysql/{print $0}' /etc/passwd                   //三条指令结果一样

awk '!/mysql/{print $0}' /etc/passwd                  //输出不匹配mysql的行

awk '/mysql|mail/{print}' /etc/passwd

awk '!/mysql|mail/{print}' /etc/passwd

awk -F: '/mail/,/mysql/{print}' /etc/passwd         //区间匹配

#//匹配包含27为数字开头的行,如27,277,2777...
awk '/[2][7][7]*/{print $0}' /etc/passwd               

awk -F: '$1~/mail/{print $1}' /etc/passwd           //$1匹配指定内容才显示

awk -F: '{if($1~/mail/) print $1}' /etc/passwd     //与上面相同

awk -F: '$1!~/mail/{print $1}' /etc/passwd          //不匹配

awk -F: '$1!~/mail|mysql/{print $1}' /etc/passwd        

IF语句

必须用在{}中,且比较内容用()扩起来

awk -F: '{if($1~/mail/) print $1}' /etc/passwd                                       //简写

awk -F: '{if($1~/mail/) {print $1}}'  /etc/passwd                                   //全写

awk -F: '{if($1~/mail/) {print $1} else {print $2}}' /etc/passwd            //if...else...

AWK 数组

AWK 可以使用关联数组这种数据结构,索引可以是数字或字符串。

AWK关联数 组也不需要提前声明其大小,因为它在运行时可以自动的增大或减小。

数组使用的语法格式:

array_name[index]=value
  • array_name:数组的名称
  • index:数组索引
  • value:数组中元素所赋予的值

.csv文件:以,作为字段分隔符,在Windows中可以直接用excel打开

  

练习

1.只显示df -h结果的第一列文件系统

df -h | awk '{print $1}'

2.显示passwd文件的第5行和第10行的行号和用户名

 awk  -F: 'NR==10 || NR==5{print NR,$1}' /etc/passwd

3.使用NF变量显示passwd文件倒数第二列的内容

awk  -F: '{print NR,$(NF-1)}' /etc/passwd

4.显示passwd文件中第5到第10行的用户名

 awk  -F: 'NR==10 || NR==5{print $1}' /etc/passwd

5.显示passwd文件中第7列不是bash的用户名

awk  -F: '$7 !="/bin/bash"{print $7}' /etc/passwd

6.显示passwd文件中行号是5结尾的行号和整行内容

 cat /etc/passwd | awk 'NR~/5$/{print NR,$0}'

7.用ifconfig/ip add  只显示ip
yum  install net-tools  -y -->安装ifconfig命令的软件

ifconfig | awk 'NR==2{print $2}'
ip add |awk '/inet.*ens[0-9]+$/{split($2,a,"/");print a[1]}'

8.ifconfig 命令后使用awk显示ens33的入站流量和出站流量(字节)

ifconfig | awk 'NR==5 ||NR==7{print $5}'
#观察流量每两秒的变化
watch -n 2 -d "ifconfig |awk 'NR==5{print $5}'"

9.使用awk命令统计以r开头的用户名和用户数目

 cat /etc/passwd | awk -F: 'BEGIN{i=0}/^r/{i++;print $1}END{print i}'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值