awk详解

简介

awk 命令利用一组用户提供的指令来将一组文件与用户提供的扩展正则表达式比较,一次一行。然后在任何与扩展正则表达式匹配的行上执行操作。

awk 命令的模式搜索比 grep 命令的搜索更常用,且它允许用户在输入文本行上执行多个操作。awk 命令编程语言不需要编译,并允许用户使用变量、数字函数、字符串函数和逻辑运算符。

语法

awk [OPTIONS] -f program_file [--] filename_list

awk [OPTIONS] [--] program filename_list

输出语句

print

语法:

print [ ExpressionList ] [ Redirection ] [ Expression ]

 ExpressionList 参数指定的每个表达式的值写至标准输出。

 Redirection 参数重定向输出,此参数可指定使用 >(大于号)、>>(双大于号)和 |(管道)进行的三种输出重定向。 

Expression 参数是文件的路径名称

[root@n1 ~]# cat 1.txt
smiley, allen
smith, alan
smithern, harry
smithhern, anne
smitters, alexis
[root@n1 ~]# awk -F "," '{print $1}'
[root@n1 ~]# awk -F "," '{print $1}' < 1.txt > 2.txt
[root@n1 ~]# awk -F "," '{print $1}' < 1.txt | echo 1

printf

语法:
printf Format [ , ExpressionList ] [ Redirection ] [ Expression ]

printf 语句将 ExpressionList 参数指定的表达式以 Format 参数指定的格式写至标准输出。除了 c 转换规范(%c)不同外,printf 语句和 printf 命令起完全相同的作用。Redirection 和 Expression 参数与在 print 语句中起相同的作用。

[root@n1 ~]# awk -F "," '{printf("type:%s\tname:%s\n",$1,$2)}' < 1.txt
  • 格式符:
  • %d,%i:十进制整数;
  • %f:显示浮点数;
  • %s:显示字符串;
  • %u:无符号整数;
  • %%:显示%自身。
  • 修饰符:
  • N:显示宽度;N为数值,宽度不足时若为左对齐则右边空格补足,若右对齐则左边空格补足。
  • -:左对齐;
  • +:显示数值正负号。
  • 0:表示以0填充。

特殊变量

ARGV:命令行参数数组。从0开始计数直到ARGC-1。
ARGC:ARGV数组元素的个数。
FILENAME:当前处理的文件名。
FNR:当前处理文件的记录号。(file record num)
NR:已处理的总记录数。多个文件时不重置。(record num)
NF:当前记录的字段总数。(field num)
FS:输入的字段分隔符。默认为空白。(file separate)
OFS:输出的字段分隔符。默认为空白。(output record separate)
RS:输入流的记录分隔符。默认为"\n"。(record separate)
ORS:输出流的记录分隔符。默认为"\n"。(output record separate)
OFMT:printf输出数值转换成字符串输出时的格式。默认为"%.6g"。
CONVFMT:printf输出数值转换成字符串输出时的格式。会被OFMT覆盖。默认为"%.6g"。
RLENGTH:被match函数匹配的字符串的长度。
RSTART:被match函数匹配的字符串的开始位置。
SUBSEP:下标分隔符。默认为"\034",ASCII中034代表的是双引号'"'

关系表达式

关系运算符 <(小于)、>(大于)、<=(小于或等于)、>=(大于或等于)、= =(等于)和 ! =(不等于)可用来形成模式。

识别转义序列转义序列 

转义序列   含义
\"          \"(双引号)标记
\/          /(斜杠)字符
\ddd     其编码由 1、2 或 3 位八进制整数表示的字符,其中 d表示一个八进制数位
\\          \ ( 反斜杠 ) 字符
\a      警告字符
\b      退格字符
\f       换页字符
\n      换行符(请参阅以下的注)
\r       回车字符
\t       跳格字符
\v      垂直跳格

正则表达式

[root@n1 ~]# cat file3
smiley, allen
smith, alan
smithern, harry
smithhern, anne
smitters, alexis

字符

功能

示例

+

匹配一个或多个前导字符

[root@n1 ~]# awk '/smith+ern/' file3

smithern, harry

smithhern, anne[root@n1 ~]# awk '/smith+ern/' file3

smithern, harry

smithhern, anne

?

匹配 0 个或 1 个前导字符

[root@n1 ~]# awk '/smith?/' file3

smith, alan

smithern, harry

smithhern, anne

smitters, alexis[root@n1 ~]# awk '/smith?/' file3

smith, alan

smithern, harry

smithhern, anne

smitters, alexis

|

[root@n1 ~]# awk '/alan|allen/' file3

smiley, allen

smith, alan

( )

组合字符串

[root@n1 ~]# awk '/a(ll)?(nn)?e/' file3

smiley, allen

smithhern, anne

x{m}

x重复m次

[root@n1 ~]# awk '/h{2}/' file3

smithhern, anne

x{m,}

x重复至少m次

[root@n1 ~]# awk '/h{1,}/' file3

smith, alan

smithern, harry

smithhern, anne

x{m, n}

x重复至少m次,但不超过n次

[root@n1 ~]# awk '/h{1,2}/' file3

smith, alan

smithern, harry

smithhern, anne

[String]

指定正则表达式与方括号内 String 变量指定的任何字符匹配

[root@n1 ~]# awk '/smi[a-l]/' file3

smiley, allen

[^ String]

内容与string变量不进行匹配

[root@n1 ~]# awk '/smi[^a-l]/' file3

smith, alan

smithern, harry

smithhern, anne

smitters, alexis

~,!~

表示指定变量与正则表达式匹配或不匹配

[root@n1 ~]# awk '$1 ~ /n/' file3(匹配第一个字段有n的)

smithern, harry

smithhern, anne

^

行首定位符

[root@n1 ~]# awk '$2 ~/^h/' file3

smithern, harry

$

行尾定位符

[root@n1 ~]# awk '$2 ~/s$/' file3

smitters, alexis

. 

匹配任意单个字符

[root@n1 ~]# awk '/a..e/' file3

smiley, allen

smithhern, anne

*

匹配 0 个或多个前导字符(包括回车)

[root@n1 ~]# awk '/a.*e/' file3

smiley, allen

smithhern, anne

smitters, alexis

\

转义字符

/a\/\// ,匹配a//

​BEGIN 和 END 模式

用 BEGIN 模式指定的操作在读取任何输入之前执行。用 END 模式指定的操作在读取了所有输入后执行

语法:

BGEIN{ACTIONS}PATTERN{ACTIONS}END{ACTIONS}

[root@n1 ~]# cat file1
1 zhang
2 qiao
3 wang
4 li
用BEGIN输出头部内容,END总结行数
[root@n1 ~]# awk -F "," 'BEGIN{print "type name"}{print $1 $2}END{print "total:" NR}' < file1
type name
1 zhang
2 qiao
3 wang
4 li
total:4

数组

awk的数组和shell的数组类似,都支持数值index的普通数组和字符串index的关联数组,其实数值index仍然会转换成字符串格式的index,所以awk的数组类型都是关联数组。

格式:array_name[index]

赋值:array_name[1]=zhang

引用:array_name[1]

删除数组:delete array_name

                delete array_name[1]

如果index是字符串,需要用双引号,否则会被当成变量

流程控制语句

条件判断语句

if (expression) statements

if (expression) statements else statements

[root@n1 ~]# cat file2
1 2 3 4
[root@n1 ~]# awk '{if ($1 < $2)print $2 " is big"}' file2
2 is big

while循环
while (expression) statements

[root@n1 ~]# awk '{i=1;while(i<=NF){print NF,$i;i++}}' file2
4 1
4 2
4 3
4 4

do循环

do statements while (expression)

[root@n1 ~]# awk '{i=1;do{print NF,$i;i++;}while(i<=NF)}' file2
4 1
4 2
4 3
4 4

for循环

for (expression; expression; expression) statements

for (expression in array) statements

[root@n1 ~]# awk '{for (i=1;i<=NF;i++){if($i == 4){ print $i "over"; }else{print $i;}}}' file2
1
2
3
4over

遍历数组
[root@n1 ~]# awk 'BEGIN{arr[1]="zhang";arr[2]="li";for(i in arr){print arr[i]}}'
zhang
li

影响循环的动作

break:退出循环。

continue:退出当前循环,进入下一个循环

next:读入下一行,并awk程序的顶端从头开始。这个awk程序是PATTERN{action}这部分,不包括BEGIN{action}。

exit code:直接进入END,若本就在END中,则直接退出awk。如果END中的exit没有定义code,则采用前一个exit的code。

内置函数

awk 命令语言使用算术函数、字符串函数和一般函数。如果打算编写一个文件,且稍后在同一个程序里读取它,那么 close 子例程语句是必需的。

算术函数

  • atan2( y, x )      返回 y/x 的反正切。
  • cos( x )             返回 x 的余弦;x 是弧度。
  • sin( x )              返回 x 的正弦;x 是弧度。
  • exp( x )             返回 x 的指数函数。
  • log( x )              返回 x 的自然对数。
  • sqrt( x )             返回 x 平方根。
  • int( x )               返回 x 的截断至整数的值。
  • rand( )               返回任意数字 n,其中 0 <= n < 1。
  • srand( [Expr] )     将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。

字符串函数

  •    index(str1,str2):返回子串str2在字符串str1中第一次出现的位置。如果没有指定str1,则返回0。
  •    length(str1):返回字符串str1的长度。如果未给定str1,则表示计算"$0"的长度。
  •    substr(str1,p):返回str1中从p位置开始的后缀字符串。
  •    substr(str1,p,n):返回str1中从p位置开始,长度为n的子串。
  •    sub(regexp,rep,str2):将str2中第一个被regexp匹配的字符串替换成rep,替换成功则返回1(表示替换了1次),否则返回0。注意是贪婪匹配。
  •    sub(regexp,rep):将"$0"中第一个被regexp匹配的字符串替换成rep,替换成功则返回1,否则返回0。注意是贪婪匹配。
  •    gsub(regexp,rep,str2):将str2中所有被regexp匹配的内容替换成rep,并返回替换的次数。
  •    gsub(regexp,rep):将"$0"中所有被regexp匹配的内容替换成rep,并返回替换的次数。
  •    match(str1,regexp):如果regexp能匹配str1,则返回匹配起始位置。否则返回0。它会设置内置变量RSTART和RLENGTH的值。
  •    split(str1,array,sep):使用字段分隔符sep将str1分割到数组array中,并返回数组的元素个数。如果未指定sep则采用FS的值。因此该函数用于切分字段到数组中,下标从1开始。
  •    sprintf(fmt,expr):根据printf的格式fmt,返回格式化后的expr。
  •    toupper(str):将str转换成大写字母,并返回新串。
  •    tolower(str):将str转换成小写字母,并返回新串。
#index、length、toupper、match、substr
[root@n1 ~]# awk 'BEGIN{
print index("realxwxw","xw")
print length("realxwxw")
print toupper("realxwxw")
print match("realxwxw","xw.*")
print substr("realxwxw",7)
}'
5
8
REALXWXW
5
xw

#split
[root@n1 ~]# awk 'BEGIN{
> name="zhang:li:qiao:wang"
> split(name,array,":")
> for(i in array){
> print array[i]}
> }'
wang
zhang
li
qiao

#sprintf
[root@n1 ~]# awk 'BEGIN{     
name="zhang:li:qiao:wang"
split(name,array,":")
for(i in array){
print sprintf("name:%s",array[i])}
}'
name:wang
name:zhang
name:li
name:qiao

#sub
[root@n1 ~]# awk 'BEGIN{
name="zhang:li:qiao:wang"
print sub(/q.*o/,"xxx",name)
print name}'
1
zhang:li:xxx:wang

#gsub
[root@n1 ~]# awk 'BEGIN{
str1="realxwxwxw"
print gsub(/xw/,"qq",str1)
print str1}'
3
realqqqqqq

自定义函数

function name ( parameter, parameter, parameter, ... ) {

                        statements

                        return expression                 

        }

示例:

计算x+y
[root@n1 ~]# awk 'function sum(x,y){ z=x+y;return z;}BEGIN{print sum(1,2)}'
3

getline函数

getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1。

示例:

执行date,通过管道符输出给getline,并赋值给d,在输出d
[root@n1 ~]# awk 'BEGIN{"date" | getline d;print d}'
Sun Apr 14 11:15:53 CST 2019

打印ls
[root@n1 ~]# awk 'BEGIN{while ("ls" |getline > 0){print}}'
1.txt
2.txt
anaconda-ks.cfg
file1
file2
file3
test_sh

统计/etc/passwd中的行数
[root@n1 ~]# awk 'BEGIN{while (getline < "/etc/passwd" > 0) {l++} print l}'
32

向awk传递变量

通过-v传递

[root@n1 ~]# awk -v name="zhang" 'BEGIN{print name}'
zhang

通过参数数组ARGV

[root@n1 ~]# awk -F "\t" 'BEGIN{
for(i=0;i<ARGC;i++){
print "ARGV["i"]:" ARGV[i]
}
print "ARGC:" ARGC
}' "a" "b"
ARGV[0]:awk
ARGV[1]:a
ARGV[2]:b
ARGC:3

#ARGV[0]存储的是awk命令

给变量加"''"(双引号,单引号)

[root@n1 ~]# name=qiao
[root@n1 ~]# awk 'BEGIN{print "'$name'"}'
qiao

实战

1.匹配/etc/passwd中有root的行
awk -F”:” ‘/root/‘ /etc/passwd

2.统计/etc/passwd的账户人数
awk ‘{count++}END{print “user count is”,count}’ /etc/passwd

3.计算某个文件夹下的文件大小
ls -l | awk ‘BEGIN{size=0;}{size=size+$5}END{print “size is”,size}’

4.统计某个文件夹下的文件占用的字节数,过滤5075892大小的文件
ls -l | awk ‘BEGIN{size=0;print “[start]size:”,size} {if($5!=5075892){size=size+$5;}}END{print “[end]size:”,size}’

5.将文件中有li的行输出
awk ‘/li/ {print $0}’ t.txt

6.输出文件中每行字符超过10的记录
awk ‘length($0) > 10’ 1.txt
7.输出1-7
awk ‘BEGIN { for (i = 1; i <= 7; i++) print i }’
8.输出偶数行的记录
awk ‘NR%2==0’ data
9.指定脚本执行
cat test.awk

#!/bin/bashBEGIN{print n1,n2}

awk -f test.awk -v n1=”hello” -v n2=”yuehuan”

11.在test2.awk中调用test1.awk中的内容
[root@t1 ~]# cat test1.awk

#!/bin/bash

BEGIN{print "this is test1.awk"}

[root@t1 ~]# cat test2.awk
@include “test1.awk”
BEGIN{print “this is test2.awk” }
[root@t1 ~]# awk -f test2.awk
this is test1.awk
this is test2.awk
12.输出记录中有J的所有域
awk ‘{if($1 ~ /J/)print $0}’ data

13.输出/etc/passwd第三域大于100的记录
awk -F”:” ‘$3>100’ /etc/passwd

14.打印行号小于15,并且最后一域匹配bash的信息
awk -F”:” ‘{if($NR<15 && $NF~/bash/)print $0}’ /etc/passwd

15.打印/etc/passwd中第一域为centos的最后一域
awk -F”:” ‘{if($1~/centos/)print $NF}’ /etc/passwd

16.设当用户ID小于500时,输出系统用户,大于500时,输出普通用户
awk -F: ‘{usertype=$3<500?”系统用户”:”普通用户”;print $1,usertype}’ /etc/passwd

17.将多行1-9的数字打印为3个数字一行
awk ‘ORS=NR%3?” “:”\n”‘ 1.txt
三目运算,取余为0,则输出\n,否则输出空格

 

参考:

https://www.cnblogs.com/f-ck-need-u/p/7509812.html#5-

https://www.cnblogs.com/losbyday/p/5854707.html

https://www.ibm.com/support/knowledgecenter/zh/ssw_aix_72/com.ibm.aix.cmds1/awk.htm#awk__a171c1266

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

real向往

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

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

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

打赏作者

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

抵扣说明:

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

余额充值