awk常用语法

本文详细介绍了awk命令的常用语法,包括打印域、匹配样式后打印、BEGIN和END语句、分隔符设置、变量NR、外部变量与内部变量的使用、printf函数、if和while语句、for循环、数组操作以及内置函数的运用。通过实例展示了awk在处理文件记录、样式匹配和数据处理方面的强大功能,适用于系统管理和日志分析等场景。
摘要由CSDN通过智能技术生成

awk命令用于对文件中匹配样式的记录进行输出,统计和其他处理操作。与sed命令相比,awk在对行的各个域进行处理时更有优势。

awk命令语法:
awk pattern { ACTION }

在awk读取文件的过程中中,变量$0保存整行的内容,变量$1保存第1个域的内容,$2保存第二个域的内容,…。

变量NF保存行包含的域的数量,因此变量$NF保存最后一个域的内容,$NF-1保存倒数第二个域的内容,…。

变量NR保存行的序号。

1.打印域

1)更换顺序打印域2,域1和域3。

awk '/^[^#]/{print $2, $1, $3}' /etc/fstab
/ /dev/mapper/rhel-root xfs
/boot UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b xfs
/u01 /dev/mapper/rhel-home xfs
swap /dev/mapper/rhel-swap swap
/dev/shm tmpfs tmpfs

2)打印每行含有的域数。

awk '/^[^#]/{print "Record:", NR, "has", NF, "fields."}' /etc/fstab
Record: 9 has 6 fields.
Record: 10 has 6 fields.
Record: 11 has 6 fields.
Record: 12 has 6 fields.
Record: 13 has 6 fields.

3)打印每个域的长度。

awk -F: '/oracle/{for(i=1;i<=NF;i++) print "Field",$i, "has", length($i), "letters."}' /etc/passwd
#将结果打印输出到文件/tmp/file.txt
awk -F: '{print "Field 1", "has", length($1), "letters." > "/tmp/file.txt"}' /etc/passwd

2.匹配样式后打印域

1)匹配swap行后再打印相关域。

awk '/swap/{print $2, $1, $3}' /etc/fstab
swap /dev/mapper/rhel-swap swap

2)匹配定义的CASE号规则后打印行。

echo "1-2345598" | awk '/^[0-9]+$/ || /^[0-9]-[0-9]+$/ {print}'

3)匹配|(或)定义的条件后打印行。

 netstat -an  |awk '/CLOSE_WAIT|ESTABLISHED|TIME_WAIT|LISTEN/ {print $0}'

4)匹配和打印两个日期之间的日志。

awk '/Sep 22/{a=1}a{b=b?b"\n"$0:$0;if(b~/Sep 23/){print b;b=""}}' messages-20210926

#使用'"和"'将变量包含在//符号里从而引用变量
date1='Sep 22'
date2='Sep 23'
awk ''"/$date1/"'{a=1}a{b=b?b"\n"$0:$0;if(b~'"/$date2/"'){print b;b=""}}' messages-20210926

或者直接在变量前后加上’“和"'引用变量。

awk '/'"$date1"'/{a=1}a{b=b?b"\n"$0:$0;if(b~/'"$date2"'/){print b;b=""}}' messages-20210926

sed命令也有类似的功能。

sed -n '/'"$date1"'/{p;:1;n;:2;/'"$date2"'/{p;b1};N;b2}' messages-20210926

3.BEGIN和END语句

在BEGIN语句中,可以存放在读取和处理文件前要执行的操作,一般用于打印报告的标题和更改内在变量的值。
在END语句中,用以存放文件的所有记录在被读取和处理后的操作,一般用于打印总结性的描述或数值总和。

awk 'BEGIN {print "Begin..."} ;/#[H-L]o/ {print $0}; /#P[e-o]/ {print $0} ;END{ print "The End"}' /etc/ssh/sshd_config
Begin...
#Port 22
#HostKey /etc/ssh/ssh_host_dsa_key
#LogLevel INFO
#LoginGraceTime 2m
#HostbasedAuthentication no
#PermitEmptyPasswords no
#PermitTTY yes
#PermitUserEnvironment no
#PidFile /var/run/sshd.pid
#PermitTunnel no
The End

4.分隔符

1)输入分隔符

变量FS保存域的输入分隔符,默认是空格或Tab。在awk命令中使用-F参数或者在BEGIN语句中定义FS变量可以更改域的输入分隔符值。

如果域分隔符同时有几种类型,使用双引号“”和中括号[]将各种分隔符放入其中(“[ :]”),或者使用双引号“”和或者符号|把各种分隔符包含在内(" |:")。

#获取系统用户的最大USER ID

awk -F: '{print $3}' /etc/passwd |sort -n |tail -1

多种输入分隔符示例:

cat file2
root /:root:/bin/sh
grid /u01/app:oinstall:/bin/bash
oracle /u01/app/oracle:dba:/bin/ksh

awk -F"[ :]" '{print $1, $3}' file2
root root
grid oinstall
oracle dba

awk 'BEGIN{FS=" |:"};{print $1, $3}' file2
root root
grid oinstall
oracle dba

awk 'BEGIN{FS="[ :]"};{print $1, $3}' file2
root root
grid oinstall
oracle dba

2)输出分隔符

变量OFS保存域的输出分隔符,默认是空格。

无输出分隔符示例:

awk 'BEGIN{FS="[ :]"};{print $1 $2 $3 $4}' file2
root/root/bin/sh
grid/u01/appoinstall/bin/bash
oracle/u01/app/oracledba/bin/ksh

默认以空格为输出分隔符示例:

awk 'BEGIN{FS="[ :]"};{print $1,$2,$3,$4}' file2
root / root /bin/sh
grid /u01/app oinstall /bin/bash
oracle /u01/app/oracle dba /bin/ksh

以Tab为输出分隔符示例:

awk 'BEGIN{FS="[ :]"};{print $1"\t"$2"\t"$3"\t"$4}' file2
root    /       root    /bin/sh
grid    /u01/app        oinstall        /bin/bash
oracle  /u01/app/oracle dba     /bin/ksh
awk 'BEGIN{FS="[ :]";OFS="\t"};{print $1,$2,$3,$4}' file2
root    /       root    /bin/sh
grid    /u01/app        oinstall        /bin/bash
oracle  /u01/app/oracle dba     /bin/ksh

5.变量NR

变量NR计算从文件中读入的行数,每读一行变量NR的值就更新一次。

读取文件完成后显示文件包含的行数:

grep -E -v "^#|^[ ]*$" /etc/fstab |awk '{print $2, $1} END {print "The number of lines of fstab is " NR}'
/ /dev/mapper/rhel-root
/boot UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b
/u01 /dev/mapper/rhel-home
swap /dev/mapper/rhel-swap
/dev/shm tmpfs
The number of lines of fstab is 5

输出第8行后的行的各个域:

awk 'NR>8 {print $2, $1, $3}' /etc/fstab
/ /dev/mapper/rhel-root xfs
/boot UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b xfs
/u01 /dev/mapper/rhel-home xfs
swap /dev/mapper/rhel-swap swap
/dev/shm tmpfs tmpfs

统计第8行以后每行包含的域数:

 awk 'NR>8 {print NF}' /etc/fstab
6
6
6
6

6.使用外部变量和定义内部变量

如第2节所示,使用单引号加双引号‘“$var”’(使用双引号加单引号在某些Linux系统中可以某些Linux版本不可以,因此不建议使用)可以在awk命令中引用shell或脚本中定义的外部变量。

引用外部变量var示例:

var="priv1"
awk '/'"$var"'/{print $3}' /etc/hosts
rac1-priv1
rac2-priv1

定义内部变量counter示例:

 awk '/^[^#]/{counter=counter+1;print} END {print "The number of lines of fstab is " counter "."}' /etc/fstab
/dev/mapper/rhel-root   /                       xfs     defaults        0 0
UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b /boot                   xfs     defaults        0 0
/dev/mapper/rhel-home   /u01                 xfs     defaults        0 0
/dev/mapper/rhel-swap   swap                    swap    defaults        0 0
tmpfs   /dev/shm        tmpfs   defaults,size=21G      0       0
The number of lines of fstab is 5.

累计某列的值示例:

awk '{total=total+$2;print "Field 2 = " $2} END {print "Total=" total}' file3
Field 2 = 100000
Field 2 = 120000
Field 2 = 30000
Field 2 = 20000
Field 2 = 50000
Field 2 = 80000
Field 2 = 30000
Field 2 = 20000
Total=450000

统计符合某个分类的值:

awk 'BEGIN {Ncount=0;Scount=0}
     BEGIN {printf "%s %10s %10s \n", "Record#", "Region", "Price"}
     /north/ {printf "%6d %10s %10s \n",NR,$1,$2,Ncount=Ncount+1}
     /south/ {printf "%6d %10s %10s \n",NR,$1,$2,Scount=Scount+1}
     END {print "Total of North region is:", Ncount, "."}
     END {print "Total of South region is:", Scount, "."}' file3

Record#     Region      Price 
     2      north     120000 
     3  northwest      30000 
     4  northeast      20000 
     6      south      80000 
     7  southeast      30000 
     8  southwest      20000 
Total of North region is: 3 .
Total of South region is: 3 .

7.printf函数

printf以定义的格式输出字符和数字,语法如下:
printf(“字符串格式” [,数值])

字符串的格式包括%d(整数),%f(浮点数),%c(字符),%s(字符串)。
如果需要格式化字符串的宽度,则可以在以上格式中加上相应的数字,如%15s代表长度为15的字符串。
输出默认是右对齐,如果需要左对齐,则在%后加上-即可。

printf输出示例:

awk '/^[^#]/{printf("%-45s %-19s %-9s %-20s %-1d %1d \n", $1,$2,$3,$4,$5,$6)}' /etc/fstab
/dev/mapper/rhel-root                         /                   xfs       defaults             0 0 
UUID=722b5e8f-6da6-4eba-abfe-8c6e7fddd67b     /boot               xfs       defaults             0 0 
/dev/mapper/rhel-home                         /u01                xfs       defaults             0 0 
/dev/mapper/rhel-swap                         swap                swap      defaults             0 0 
tmpfs                                         /dev/shm            tmpfs     defaults,size=21G    0 0 

8.awk if语句

在awk语句中,可以使用if来判断域是否满足定义的规则,并根据判断条件进行相应的操作。

在awk语句中if的使用格式如下:
if (判断条件) { 执行代码块1}
else { 执行代码块2 }

if (判断条件1) {
if (判断条件2) { 执行代码块1 }
else { 执行代码块2 }
}

1)比较数字

关系操作符说明
==等于
!=不等于
>大于
<小于
>=大于等于
<=小于等于

示例:

awk '{num= $2 / $3; if(num>5) print $1,num}' file3
east 10
north 13.3333
west 7.14286
south 10

2)比较字符串

关系操作符说明
==等于
!=不等于
~包含正则表达式样式
!~不包含正则表达式样式

示例:

awk '{if($1 ~ /north/) print $1, $3}' file3
north 9000
northwest 6000
northeast 5000

awk '{if($1 == "north") print $1, $3}' file3
north 9000

username="grid"
awk -F: '{if($4 ~/\<'"$username"'\>/) print $0}' /etc/group
dba:x:502:oracle,grid
asmadmin:x:504:grid
asmdba:x:506:grid,oracle
asmoper:x:507:grid

awk -F: '{if($4 ~/\<'"$username"'\>/) print $1}' /etc/group
dba
asmadmin
asmdba
asmoper

3)逻辑运算

逻辑运算符说明
&&逻辑与
||逻辑或
!逻辑非

示例:

awk '{if($1 ~ /north/ && $3 > 5000) print $1, $3}' file3
north 9000
northwest 6000

4)数学运算

数学运算符说明
+
-
*
/
%求余
^指数运算
++变量加1
变量减1

示例:

awk '/grid/{counter++;print} END {print "#The number of groups to which the user grid belongs is " counter "."}' /etc/group
dba:x:502:oracle,grid
asmadmin:x:504:grid
asmdba:x:506:grid,oracle
asmoper:x:507:grid
#The number of groups to which the user grid belongs is 4.

9.awk while语句

语法:
while (判断条件) 执行代码

while (判断条件) {
执行代码块
}

do {
执行代码块
} while (判断条件)

打印所有列示例:

awk '{i=1}; {while (i <= NF) {print $i; i++}}' file4
sdb
sdc
sde
sdf
sdg
sdi

10.awk for语句

语法:
for (初始条件语句; 判断条件; 每步条件变化语句)
{执行代码块}

for (数组的索引)
{执行代码块}

打印所有列示例:

awk '{for(i=1;i<=NF;i++)print $i}' file4
sdb
sdc
sde
sdf
sdg
sdi

以倒序打印文件的所有行:

cat file3
east 100000 10000
north 120000 9000
northwest 30000 6000
northeast 20000 5000
west 50000 7000
south 80000 8000
southeast 30000 6000
southwest 20000 4000

awk '{line[NR]=$0}; END{for(c=NR;c>0;c--)print line[c]}' file3
southwest 20000 4000
southeast 30000 6000
south 80000 8000
west 50000 7000
northeast 20000 5000
northwest 30000 6000
north 120000 9000
east 100000 10000

11.数组

在awk语句中,数组不需要定义就可以直接使用,而且数组的索引不需要是数字,任意与要存储的值相关的字符串都可以用来作为数组的索引(index)。

数组存储的值还可以使用以下方法来引用:
for (数组的索引)
{执行代码块}

统计某列中各个值的数量:

# cat file3
east 100000 10000
north 120000 9000
northwest 30000 6000
northeast 20000 5000
west 50000 7000
south 80000 8000
southeast 30000 6000
southwest 20000 4000
center  25000   5000

awk '{a[$3]++} END{for(i in a)print i,a[i]}' file3
10000 1
7000 1
8000 1
4000 1
9000 1
5000 2
6000 2

进程资源使用多少排序:

ps -eo 'user s pri pid ppid pcpu pmem vsz rss stime time nlwp psr args'|awk 'NR==1{print} NR!=1{r[++n]=$0} END{for(i in r)print r[i]|"sort -rn -k6 -k7"} '

USER     S PRI   PID  PPID %CPU %MEM    VSZ   RSS STIME     TIME NLWP PSR COMMAND
root     S  19  2271     1  0.2  1.1 4700804 290364 Oct19 00:07:52 38   1 /u01/app/19.0.0/grid/jdk/jre/bin/java -server -Xms128m -Xmx256m -Djava.awt.headless=true -Ddi
sable.checkForUpdate=true -XX:ParallelGCThreads=5 oracle.rat.tfa.TFAMain /u01/app/19.0.0/grid/tfa/rac1/tfa_home
root     S  19  1432     1  0.1  0.0 114156  2280 Oct19 00:03:58    1   2 /bin/sh /etc/init.d/init.ohasd run >/dev/null 2>&1 </dev/null
gdm      S  19  2338  2211  0.0  0.5 3773248 141564 Oct19 00:00:43 33   2 /usr/bin/gnome-shell
rtkit    S  18   985     1  0.0  0.0 196848  1732 Oct19 00:00:01    3   7 /usr/libexec/rtkit-daemon
rpc      S  19   963     1  0.0  0.0  69220  1056 Oct19 00:00:00    1   2 /sbin/rpcbind -w
root     S  90   376     2  0.0  0.0      0     0 Oct19 00:00:00    1   7 [irq/16-vmwgfx]
root     S  39   931     2  0.0  0.0      0     0 Oct19 00:00:00    1   5 [xprtiod]
root     S  39   930     2  0.0  0.0      0     0 Oct19 00:00:00    1   7 [rpciod]
root     S  39    92     2  0.0  0.0      0     0 Oct19 00:00:00    1   5 [deferwq]
root     S  39   905     2  0.0  0.0      0     0 Oct19 00:00:00    1   1 [xfs-eofblocks/d]
root     S  39   904     2  0.0  0.0      0     0 Oct19 00:00:00    1   1 [xfs-log/dm-2]

12.awk内置函数

1)字符串函数

函数说明
gsub(r,s[,t])使用字符串s替换字符串t中匹配正则表达式r的所有字符串。函数返回替换的次数。如果字符串t未提供,则缺省是$0。
sub(r,s[,t])使用字符串s替换字符串t中匹配正则表达式r的第一个字符串。如果成功返回1,否则返回0。如果字符串t未提供,则缺省是$0。
index(str,substr)返回字符串substr在字符串str中第1次出现的位置,如果未找到则返回0
length(str)返回字符串的长度
match(s,r)在字符串s中匹配正则表达式r的字符串,返回正则表达式r在s中匹配开始的位置,如果未找到则返回0
split(string,array[,sep])将字符串string分割成数组array,如果分隔符sep没有指定,则使用FS作为分隔符,返回数组的元素数量。
substr(string,m[,n])返回字符串string在起始位置m和包含n个字符的子字符串。如果n没有提供,则返回从m开始直到字符串末尾的所有字符。
tolower(string)将所有大写字符串转换成小写字符串,返回新字符串。
toupperr(string)将所有小写字符串转换成大写字符串,返回新字符串。

取某列的子字符串再转换成大写:

cat file2
root /:root:/bin/sh
grid /u01/app:oinstall:/bin/bash
oracle /u01/app/oracle:dba:/bin/ksh

awk '{print toupper(substr($1,0,5))}' file3
EAST
NORTH
NORTH
NORTH
WEST
SOUTH
SOUTH
SOUTH
CENTE

替换某列的字符串:

awk -F "[ :]" '{sub("/bin/","",$4); print $4}' file2
sh
bash
ksh

取某列的子字符串再分割:

awk -F "[ :]" '{split(substr($4,match($4,"/bin/")),a,"/"); print a[3]}' file2
sh
bash
ksh

2)IO函数

函数说明
close(filename-expr) 或 close(command-expr)关闭文件或管道。
getline [var] [<file] 或 command | getline [var]从输入,文件或管道中读取下一行
next读取下一输入行,然后进入下一个循环执行样式和过程语句
delete array[element]删除数组array中的一个元素
print[args][destination]打印arg到目标输出。如果没有指定arg,默认是$0。如果destination没有指定,则输出到标准输出stdout。
printf(format [,expression(s)] [destination])按照格式要求打印,详见上面的printf函数。
sprintf(format [,expression(s)] [destination])返回格式化的字符串,不打印到输出。
system(command)执行系统命令,返回执行状态。

针对文件里的所有行调用系统命令:

awk -F: '{cmd="grep "$1" /etc/group";system(cmd)}' oracleuser|sort -u
asmadmin:x:504:grid
asmdba:x:506:grid,oracle
asmoper:x:507:grid
dba:x:502:oracle,grid
oracle:x:1000:

3)数学函数

函数说明
atan2(y,x)返回y/x的正切值
cos(x)返回x的余弦值
exp(arg)返回arg的自然指数e^arg
int(arg)返回arg的整数值
log(arg)返回arg的自然对数lnarg
rand()产生1个在0和1之间的随机数,函数返回相同的随机数,除非使用srand()函数指定了生成随机数种子
sin()返回x的正弦值
sqrt(arg)返回arg的平方根
srand(expr)指定生成随机数的种子,默认是以时间为种子

示例:

awk '{print atan2($2,$1)}' file5
1.10715
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值