shell脚本【文件操作3】awk:文本处理

一、综述

1.1  版本和历史

        目前大多数Linux发布版对于awk的支持,都提供gawkawkGNU实现)或者mawkawk的一个快速、删减版),甚至nawk。

        想要下载gawk,在Ubuntu下可以直接sudo apt-get install gawk

 

1.2  gawk工作原理

        首先:gawk命令的书写模式:

        gawk  [options]  [program]  [file-list]

        例如:

        gawk  '/^chen/{print $0}'  file            #进行正则表达式行首chen字符串匹配(pattern匹配),若匹配成功则打印整个记录(若pattern匹配成功,则执行action)。

        说明:

        [options]是一些特殊选项,一般都没有什么用,就自动省略了 :)

        [program]gawk工具的精髓。它由模式(pattern)和动作(action)组成。当然任意一方都可以缺省,也可以有多个模式和动作、其中pattern匹配可以是正则表达式和条件表达式;action中有控制语句、变量、运算符等等,可以做统计。

        [file-list]是一些想要处理的文件,中间用空格依次排开


         其次:gawk处理流程大致介绍:

        gawkfile中,一次会选择一行的内容作为输入。

        在默认输入记录分隔符为换行符的情况下,一行就是一个记录。

       在默认输入字段分隔符为空格和制表符的情况下,一个记录被分解成众多字段,存储在已编号的变量中,从$1~$n,最多100个。

     然后依次进行pattern匹配,在匹配成功后进行action处理。

     若有多个pattern,则类似于C语言中的多条语句,前一个patternaction处理完后,依次再进行下一个pattern匹配。

        在这一个记录处理完后,再读取下一行,依次重复上面的操作。


1.3  awk运用场景

        awkgrep都是文本处理工具,都有文本搜索功能,那么awk相较于grep,可以运用于那些场景,有什么优势?

        例子:

            ① 提取apache的日志,统计访问最多的ip,或者统计ssh连接的最多ip

            ② 一份记录全班成绩的文件,只想提取出里面数学成绩时

姓名

数学

语文

英语

地理

科学


        说明:

        第一种,是很常见的awk用于统计的情况,由于awk有变量,数组和控制语句,所以非常适合于做统计

        第二种,是很常见的按列提取数据的情况。awk的字段,可以把文本按列的方式显示出来

        上面这些都是grep做不到的;grep做不到统计,更做不到分列显示。点击打开链接

 

二、[program]讲解

2.1  [program]组成

        ① 模式(pattern):从输入行中选取文本行

        ② 动作(action):如果pattern匹配成功,就执行指定的action。

 

     问:为什么这部分叫program呢?

     因为这一部分确实是在写代码,不同的是,这些代码好像没有我们在C语言下面看到的那样完整:有开始,有结束的。

     之所以这样,是因为这个框架已经被内置了,我们写的这部分代码,确实是代码,不过是在awk代码框架中添加的我们想要执行的一部分代码。

     这样做的好处就是容量可以更加精简。并且awk语言也是一种解释型语言,不需要经过编译连接这样的过程。

 

2.2  [program]部分,标准格式

        格式:

‘/pattern/{action}’

        注:

        ① 整个[program]部分,用单引号括起来,表示将这部分提交给gawk命令进行执行。

        ② pattern可以缺省,即写为’{action}’。pattern缺省之后,表示对输入的每一行都执行动作。

        ③ action也可以缺省,即写为’/pattern/’。action缺省后,表示对匹配的模式执行默认的动作,即print

        ④ gawk是怎样支持基本正则表达式和扩展正则表达式的?正则表达式介绍,而这一部分就是通过模式pattern来显示的。

在匹配时,pattern可以是非完全表达,通过正则表达式来匹配想要的内容。

        ⑤ awk语言基本概念和模式说明

        awk是一门语言,它具有一个完整语言所具有的几乎所有特性。并且它有自己的语法、变量、函数、运算符、数组和控制结构,而这些都体现在action

     类似C语言的mainawk语言也有自己固定的框架,不过这个框架是固定好的,不需要我们再动手去写。

     当我们在写action时,实际是在向这个框架中添加一些我们想要的操作。

     一个动作,就类似C语言的一条语句,多个动作之间需要用;”(分号)进行分隔。这和C语言中两条语句之间通过分号分隔是一个概念。

     实际上,awk语言中很多结构都是来自C语言。

        ⑥ 多个模式,怎样进行组合问题

        如果有多个模式,则直接在前一个后面进行添加,如:

‘/pattern1/{action1}/pattern2/{action2}

     花括号就是用于分隔patternaction,以及规定一组action用的。

        pattern和其后的action是一组,缺省pattern可以写成:

‘/pattern1/{action1}{action2}’

     此时action2相应没有pattern,所以就是对所有输入的行都执行action2

 

三、[program]的pattern部分

        pattern是由正则表达式、判别条件真伪的表达式,或二者的结合构成的。

        ① 正则表达式的介绍:https://blog.csdn.net/huayangshiboqi/article/details/80514778#t4 

        ② 判别条件真伪的表达式的介绍,则由3.1 布尔运算符和3.4关系运算符这两个部分给出。

        形式:

      在pattern中,一般正则表达式的形式是:/pattern/,判别条件真伪表达式的形式是:str1 == str2  (“==”符号只是用于特定举例,可以是关系运算符或者是布尔运算符任何一个,前后两个是变量)

 

        awk虽然支持基本和扩展的正则表达式,但并不是所有的元字符它都能够支持,比如下面这些正则表达式中的元字符它就不支持。

                                                        表3.1 任何awk版本都不支持的正则表达式

元字符

说明

\< \>

单词定位

\ ( \)

向前引用

\{  \}

重复

 

3.1  pattern中的布尔运算符

     第⑥条是说要匹配多个模式。

        但是在这些模式的书写中,如何最准确的匹配出我们想要的模式?

        pattern中不仅可以使用基本和扩展的正则表达式,还可以使用布尔运算符:“||”(或)和“&&”(与),来使匹配的模式更加符合预期。

        比如:

awk ‘/a||b/{print 234}’ file

     表示匹配a或者b中的一个即可。

  gawk  ‘$2 >5 &&  $2< 15’  file

     表示如果某记录的第二个字段,值在5-15之间,就打印该记录。

3.2  pattern的特殊模式

     在模式中,可以自己去匹配自己想匹配的模式。但是,awk同时规定了两个特殊的模式:BEGINEND

        BEGIN:是在匹配开始前,执行的一种模式。

        END:是在所有匹配结束后,执行的一种模式。

        比如:

gawk  ‘BEGIN{print hello}’  file

 

3.3  pattern中的逗号

        逗号是范围运算符。

        pattern是用来匹配一种模式的。如果有两个pattern,并且中间用逗号进行隔开,则表示:从匹配第一种模式的初始行开始,到匹配到第二种模式为止,这中间所有的文本,都被选中。

        比如:

gawk  ‘FNR==2 , FNR==5’  file-list

     两种模式用逗号进行了隔开。就表示匹配第二行到第五行所有的文本,并执行默认的actionprint

    (FNR是一个变量,在4.1节中有介绍)

 

3.4  pattern中的判别条件真伪表达式

        判断条件真伪表达式,一般是由关系运算符进行操作的。

                                                                    表3.2 支持的关系运算符

运算符

含义

<

小于

<=

小于等于

==

等于

!=

不等于

>=

大于等于

>

大于

 

        示例:

gawk  ‘$2 > 2 {print $0}’  file

        如果第二个字段的数值大于2,就输出这整条记录

        注:默认,记录是按照换行符来划分的,即一行为一个记录。

     但是,输入记录分隔符是可以改变的,可以不按照换行符作为分隔符。表4.1 变量中有说明。

     使用正则表达式的pattern举例:

gawk  ‘/^marry/{print}’  file

     表示匹配行首的marry

 

3.5  pattern中的符号“~”和“!~

     作用:~”符号用于测试某个字段、记录或者变量是否匹配正则表达式。

      “!~”则正相反,用于测试某个字段、记录或者变量不匹配正则表达式。

 

     在3.4中,关系运算符主要用于数值;正则表达式则主要用于字符串。

        能不能单独对某个字段进行测试?

 

        举例:

gawk  ‘$1 ~ /marry/{print}’  file

        pattern部分是:$1~/marry/

        action部分是:print

        pattern部分的意思是:对第一个字段进行marry匹配,如果某记录(行)的第一个字段匹配成功,则打印这整个记录

 

四、[program]的action部分

        action是完全按照awk的语法来写的一组语句的集合。可以有变量、函数、运算符、控制语句等等。

     多个action之间通过“;”(分号)进行分隔。

4.1  变量

                                                                        表4.1 部分程序变量

变量

含义

$0

当前记录

$1 ~ $n

当前记录($0)中的1~n个字段

RS

输入记录分隔符(默认为换行符)

FS

输入字段的分隔符(默认空格或制表符)

NF

当前记录的字段数目

NR

当前记录的记录编号

OFS

输出字段分隔符(默认为空格)

ORS

输出记录分隔符(默认为换行符)

FILENAME

当前输入文件的名称(null表示标准输入)

FNR

区别于NR的是,是否为当前文件的记录编号

 

        gawk有两种变量:用户变量和程序变量。

        不需要在使用变量之前声明它们。不过可以选择把初始值赋予这些变量。

 

     变量即可以在pattern中,也可以使用在action中,尤其是控制语句中,作为条件判断。

     例如:打印第n行的数据:

gawk  ‘FNR==n{print}’  file-list  #变量作为模式

        或

gawk  ‘{if(FNR==n){print}}’  file-list  #把变量运用于控制语句

     前一种直接用变量进行pattern匹配,后一种是在action中使用控制循环语句进行筛选。

 

     问1NRFNR什么区别

        就是当前文件和所有文件的区别。

        gawk后面会接file-list。如果是FNR,就是file-number-of-record,只记录当前文件的行数。

     如果是NRnumber-of-record,记录的就是输入的所有文件file-list的总记录行数。

     在条件判断中,if(NR==FNR)是用来判断是否在处理第一个文件。

 

     问2NFNR的区别

        NF是字段数目;NR是记录数目

     字段和记录的区别可以参考1.2节。

        这两个变量,在读入数据流时就已经固定了。

 

     问3NFNR$0$1~$n之间的区别

        NFNR只是用于计数,是数值

        $0$1~$n都是实际从文件中读取的字符串

 

     问4:输入字段分隔符的更改

        NF,字段分隔符默认是空格和制表符。由表4.1中的FS变量可进行更改。

        例如:

     功能:按照:”(分号)分隔第一行数据流的字段,如果总字段数目大于等于2,则输出第1个字段的字段串

        ① gawk  ‘BEGIN{FS=”:”}  NR==1{if(NF>=2)  print $1}’  file

            gawk  -F:  ‘NR==1{print $1}’  file #-F选项直接接冒号

        而不能是这样:

        ② gawk  ‘NR==1{FS=”:” ; if(NF>=2) print $1}’  file

     第一种,在读取数据流之前就已经对输入字段的分隔符进行了更改,这样读取第一个数据流时,NF是成功按照“:”进行字段分隔计数的。

     第二种,在读取数据流之后,匹配之后才做输入字段分隔符的更改。此时,NF已经固定。在读取过程中,NF的数值已经按照默认分隔符进行分隔并计数,所以此时更改对它无效。

        如果有多个字段分隔符,就可以用正则表达式了:

gawk  -F’[ :\t]’  ‘NR==1{print $1}’  file

        -F后面接的是一个单引号括起来的正则表达式[ ]”符号,中间列举的均为输入字段分隔符:空格、冒号和制表符

        在写上面命令时需要注意的是:

            ⑴ 特殊符号的赋值,两端要打双引号,比如FS=”:”

            ⑵ 不同action之间要加“;(分号),比如②中的FS=”:” ; if……

 

        其它的比如:输入记录分隔符、输出记录分隔符、输出字段分隔符等,都可以按照上面这个模式进行更改。

 

4.2  函数

        gawk提供了一些用来操作数字字符串的函数

                                                                    表4.2 gawk提供的一些函数

函数

含义

length(str)

返回str中的字符个数;如果没有带str参数,则返回当前记录中的字符个数

int(num)

返回num的整数部分

index(str1,str2)

返回str2在str1中的索引,如果str2不存在就返回0

split(str,arr,del)

用del作为分隔符,将str的元素放在数组arr[1]…arr[n]中,返回数组中的元素个数

sprint(fmt,args)

根据fmt格式化args并返回格式化后的字符串

substr(str,pos.len)

返回str中从pos开始,长度为len个字符的子字符串

tolower(str)

返回str的副本,但是其中所有的大写字母被替换成相应的小写字母

toupper(str)

返回str的副本,但是其中所有的小写字母被替换成相应得大写字母

 

     比如:gawk  ‘NR==1{print length}’  file

        如果是默认记录分隔符,则返回第一行的字符个数。包括空格等符号。

 

4.3  算术运算符

        awk中很多都是借鉴C语言,算术运算符也都是来自C

                                                         表4.3 算术运算符

运算符

含义

**

*

乘积

/

%

取余

+

-

=

赋值

++

运算符前面的变量自增

--

运算符前面的变量递减

+=、-=、*=、/=、%=

前面表达式与后面表达式相作用,结果赋予前面变量


4.4控制语句

        gawk支持的控制结构:ifelsewhilefor

     两个辅助:breakcontinue(用法和C语言完全一样)

 

     三种控制结构和C语言中的用法也是大同小异。

        ① ifelse

if(condition){commands} else{commands}

        例如:

gawk  ‘if($2>5){print $0} else{print “hello”}’  file

 

        ② while

while(condition){commands}

 

        ③ for

        for有两种结构:

        一种是普通的:for(init; condition; increment) {commands}

        另一种是处理关联数组时:for(var in array){commands}

     在处理关联数组时,和shellfor控制结构处理方式很像。

     处理方式是:遍历关联数组array,每循环一次,都将array相应元素赋给var变量。

 

                                                        表4.4 控制语句常用的关系运算符

运算符

含义

<

小于

<=

小于等于

==

等于

!=

不等于

>=

大于等于

>

大于

     控制语句支持:变量、布尔运算符,和关系运算符等等(和C语言中的控制语句支持的操作是一样的)

     其中布尔运算符在pattern中也是被支持的。

 

 

 

 

 

参考:

Linux命令、编辑器与shell编程》Mark G.Sobell著 包战,孙向华,胡艮胜 译

UNIX shell范例精解》(第4版).Ellie Quigley著 李化,张国强 译 (这本书对awk、sed介绍的很全)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值