awk命令

awk命令

一、简介

先看看man手册上怎么介绍awk的: gawk - pattern scanning and processing language

可以看出awk简单来讲是具有两个功能:模式匹配和处理。这里有个疑问,man的是awk,怎么出现了gawk。awk指的是一种编程语言,用于处理文本等数据,gawk是GUN版本的awk,属于比较常用的awk版本。

二、命令执行原理

简单理解,awk是以接收到的文本的每一行为对象操作,执行指定的命令,可以理解为for语句,条件是遍历文本中的每一行,for中的代码块即是是awk后面跟随的代码块。

三、命令语法与参数

awk的基本语法:

awk 'Pattern { Action }'

Pattern,模式。awk通过模式来匹配每一行的内容,如果行内的内容和模式匹配,则提取出相应的内容,换句话说可以通过Pattern来筛选数据,之后对筛选出来的每一行数据执行action。awk里面的模式有:
1. 正则表达式
2. 关系表达式
3. 多个Pattern的逻辑组合
4. Pattern1,Pattern2
5. BEGIN 和 END

[root@redhatclient ~]# awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:          GNU long options:
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
        -m[fr] val
        -O                      --optimize
        -W compat               --compat
        -W copyleft             --copyleft
        -W copyright            --copyright
        -W dump-variables[=file]        --dump-variables[=file]
        -W exec=file            --exec=file
        -W gen-po               --gen-po
        -W help                 --help
        -W lint[=fatal]         --lint[=fatal]
        -W lint-old             --lint-old
        -W non-decimal-data     --non-decimal-data
        -W profile[=file]       --profile[=file]
        -W posix                --posix
        -W re-interval          --re-interval
        -W source=program-text  --source=program-text
        -W traditional          --traditional
        -W usage                --usage
        -W use-lc-numeric       --use-lc-numeric
        -W version              --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
        gawk '{ sum += $1 }; END { print sum }' file
        gawk -F: '{ print $1 }' /etc/passwd

四、命令实践

awk的优点在于灵活,可以通过几个简单的例子快速掌握它的原理。

1.基本功能
[root@redhatclient ~]#  cat /etc/hosts
172.0.0.1       redhatclient
192.168.50.131  masterserver
192.168.50.132  redhatclient
192.168.50.133  centosmaster
[root@redhatclient ~]# cat /etc/hosts | awk '{print $0}'
172.0.0.1       redhatclient
192.168.50.131  masterserver
192.168.50.132  redhatclient
192.168.50.133  centosmaster
[root@redhatclient ~]# cat /etc/hosts | awk '{print $1}'
172.0.0.1
192.168.50.131
192.168.50.132
192.168.50.133
[root@redhatclient ~]# 

在hosts文件里面有四行数据,在第二个命令中,对于接收到的每一行,awk都执行print 0 0 这 个 命 令 , 0指一整行的数据,$1指第一列的数据,以空格为分隔符。

2.指定分隔符 -F参数

在上面,awk默认的分隔符是空格,如果不想以空格作为每行文本内的分隔符,可以使用-F参数指定分隔符。可以看到,分隔符可以用双引号括起,也可以不用。与-F参数之间可以有空格,也可以没有。

[root@redhatclient ~]# awk -F "." '{print $0}' /etc/hosts 
172.0.0.1       redhatclient
192.168.50.131  masterserver
192.168.50.132  redhatclient
192.168.50.133  centosmaster
[root@redhatclient ~]# awk -F "." '{print $1}' /etc/hosts 
172
192
192
192
[root@redhatclient ~]# awk -F . '{print $1}' /etc/hosts 
172
192
192
192
[root@redhatclient ~]# awk -F. '{print $1}' /etc/hosts 
172
192
192
192
[root@redhatclient ~]# 
3.BEGIN与END

指定分隔符还可以指定内建变量FS,比较下面的输出

[root@redhatclient ~]# awk '{FS=".";print $1}' /etc/hosts
172.0.0.1
192
192
192
[root@redhatclient ~]# awk 'BEGIN{FS="."}{print $1}' /etc/hosts
172
192
192
192
[root@redhatclient ~]# 

可以观察到,在第一行命令中我们没有加入BEGIN模式,结果在第一行输出没有按照我们预想的那样将此行数据按照分隔符”.”来分列。这是因为:对于读取到的每一行数据,awk先读取之后再执行花括号里的脚本,那么针对第一行数据,awk先按照默认的文本分隔符(即空格)将第一行数据分行,之后才执行花括号里面的脚本,将FS修改为”.”,所以从第二行开始才会得到我们想要的输出。
我们想要的是在awk对文本做任何处理之前就执行一些初始化代码,那么就需要使用BEGIN模式,BEGIN后面跟随的脚本会在awk处理数据之前先行执行。这也就是为什么FS一定要指定在BEGIN后的脚本中。同样的,END后的脚本会在awk处理完所有的文本之后最后执行。

4.运算符

awk可以支持以下运算符:

运算符描述
= += -= = /= %= ^= *=赋值
?:C条件表达式
&&逻辑与
~ ~!匹配正则表达式和不匹配正则表达式
< <= > >= != ==关系运算符
空格连接
  • -
加,减
  • / %
乘,除与求余
    • !
一元加,减和逻辑非
^ *求幂
++ –自加或者自减
$字段引用
in数组成员

其中,正则和关系运算符可以用在模式里面,用于筛选数据。

[root@redhatclient ~]# cat /etc/hosts
172.0.0.1       redhatclient
192.168.50.131  masterserver
192.168.50.132  redhatclient
192.168.50.133  centosmaster
[root@redhatclient ~]# awk 'BEGIN{FS="."}$1==172{print $0}' /etc/hosts
172.0.0.1       redhatclient

其中$1==172就是awk中的模式,不用放在花括号中。

在比如,统计文本中有几行数据:

[root@redhatclient ~]# awk 'BEGIN{count=0}{count++}END{print count}' /etc/hosts
4

或者使用正则表达式来查询第一列中第二个数字是9的行:

[root@redhatclient ~]# awk 'BEGIN{FS="."}$1 ~ /.9./{print $1}' /etc/hosts
192
192
192
[root@redhatclient ~]# 

正则表达式以~开始,//之间是表达式的内容

5.内建变量

awk的內建变量

变量描述
$n当前记录的第n个字段,字段间由FS分隔
$0完整的输入记录
ARGC命令行参数的数目
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
CONVFMT数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO最后一个系统错误的描述
FIELDWIDTHS字段宽度列表(用空格键分隔)
FILENAME当前文件名
FNR各文件分别计数的行号
FS字段分隔符(默认是任何空格)
IGNORECASE如果为真,则进行忽略大小写的匹配
NF一条记录的字段的数目
NR已经读出的记录数,就是行号,从1开始
OFMT数字的输出格式(默认值是%.6g)
OFS输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS输出记录分隔符(默认值是一个换行符)
RLENGTH由match函数所匹配的字符串的长度
RS记录分隔符(默认是一个换行符)
RSTART由match函数所匹配的字符串的第一个位置
SUBSEP数组下标分隔符(默认值是/034)

如打印当前文件名

[root@redhatclient ~]# awk '{print FILENAME}' /etc/hosts
/etc/hosts
/etc/hosts
/etc/hosts
/etc/hosts
6.正则表达式

awk可以支持正则表达式匹配,正则表达式又是另外一门语言,这里只简单结合awk介绍下。

awk使用正则基本语法:
awk ‘/正则/{action}’ file

上面这种默认匹配 0awk 0 , 相 当 于 a w k ‘ 0 ~/正则/{action}’ file,可以指定某一列来进行正则匹配

正则匹配后默认会打印匹配到的内容,所以若主体语句仅仅是print,可直接省略。

字符含义
+匹配一个或多个加号前的字符,这个字符可以在字符串中的任何位置。
*表示匹配零个或者多个任意字符
?匹配零个或者一个问号前的字符,这个字符可以在字符串中的任何位置。
|管道符代表逻辑或的意思,只要待匹配的字符串符合管道符两边的任何一个表达式,就代表匹配成功。
()将括号内的字符组合成一体,整体匹配。
{m}匹配前面的字符m次。
{m,}匹配前面的字符>=m次。
{m,n}匹配前面的字符次数在m和n之间,包括m和n。
[string]匹配中括号里面的任意字符,可以匹配多个。
[^string]不匹配中括号里面的任何字符。
\~与!\~\~代表指定变量进行正则表达式匹配,!\~代表指定变量不匹配。
^指定匹配字段的开头。
$指定匹配字段的结尾。
.表示匹配除了在末尾的换行符之外的任何一个字符。
\反斜杠,转义字符,用在具有特殊含义的字符之前,就具有了特殊含义。\n 匹配一个换行符。\t 匹配一个制表符。\d 匹配一个数字,等价于[0-9]。\D 匹配一个非数字,等价于[^0-9]。\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。[^\s]表示任何非空白字符。\S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。[^\w]。注意\S比\w包括@#¥等更多特殊字符。

\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。[^\w]
注意\S比\w包括@#¥等更多特殊字符

通过几个小例子来理解其中的含义:

[root@redhatclient test]# cat f1
t
rt
rot
root
rooot
roooot
rootrootrootroot
[root@redhatclient test]# cat f1|awk '/r*t/'
t
rt
rot
root
rooot
roooot
rootrootrootroot
[root@redhatclient test]# cat f1|awk '/r+t/'
rt
[root@redhatclient test]# cat f1|awk '/r?t/'
t
rt
rot
root
rooot
roooot
rootrootrootroot
[root@redhatclient test]# cat f1|awk '/r.t/'
rot
[root@redhatclient test]# 

我们看到f1这个文件中有这这样的数据:

[root@redhatclient test]# cat f1
t
rt
rot
root
rooot
roooot
rootrootrootroot

其中

'/r*t/'

代表了匹配r大于等于零次,其中t是固定存在的,而r是待匹配的,处理第二行输出代表匹配了一次r之外,其余行均代表匹配了零次r。

'/r+t/'

代表匹配r一次或者多次,通过的,t是固定存在于r后的,只有第二行符合这个正则。

'/r?t/'

代表匹配r零次或者一次,通俗点讲,就是匹配字符串中在字符t前面有零个或者一个r的字符串。

再看:

[root@redhatclient test]# cat f1 |awk '/roo*t/'
rot
root
rooot
roooot
rootrootrootroot
[root@redhatclient test]# cat f1 |awk '/r(oo)*t/'
rt
root
roooot
rootrootrootroot

小括号代表了结合匹配。小括号里面的内容作为一个整体进行正则匹配,在第二个命令输出中,正则表达死代表的意思是,在字符串中匹配零个或以上的“oo“,并且在这些”oo“之前是字符r,之后是字符t。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值