shell学习-awk文本处理器-2

三、awk语言特性

3.1 awk代码特性

        通常情况下,awk会针对每一个输入执行一段代码块。但是有些时候,我们需要在awk开始处理输入之前执行一些数据的初始化。awk定义了BEGIN和END代码块,BEGIN代码块是进行awk部分参数的初始化操作,END代码块是在所有的输入都处理完后,然后awk运行代码。BEGIN和END代码块均为可选项。

3.1.1 BEGIN代码块

        在上一次的学习里,我们利用-F ":"重新定义分隔符号为冒号(:),下面展示使用BEGIN代码块实现重定义分隔符号为冒号的功能

  •         使用文件来编写awk代码

        首先,在terminal创建fs.awk文件,文件内容如下:

BEGIN {
    FS=":"
}
{
    print $1 $3
}

        awk中定义FS变量为字段分隔符,这里将冒号赋值给了FS,awk在初始化操作过程中就会将默认分隔符改变为冒号。 

       之后在terminal调用fs.awk文件,就可以实现分隔符号为冒号时输出1.rpt文件的第一列与第三列的功能。

head -n10 1.rpt | awk -f fs.awk

        上述的操作是使用一个文件来编写awk脚本,然后使用-f参数将fs.awk文件传递到命令中。

  •         使用单行语句编写awk代码

        还可以将fs.awk脚本内容写到一行里(这种方法感觉对于执行复杂的内容 书写起来相对繁琐,不太推荐):

head -n10 1.rpt | awk 'BEGIN {FS=":"} {print $1 $3}'

 3.1.2 END代码块

        END代码块中,awk可以执行一些类似于统计数据,打印输出之类的操作。

        首先,在terminal创建search.awk文件,文件内容如下:

/VIOLATED/ {++adder}    #固定匹配字符串‘VIOLATED’,如果匹配上了,就执行{}之间的内容,即++adder(不懂啥意思,还没学呢)

END {                    #end代码块执行awk脚本的扫尾工作,这段代码将统计的1.rpt中VIOLATED字符出现的次数打印出来。
    print "'VIOLATED' appears " adder " times."
}

        之后在terminal调用:

awk -f search.awk 1.rpt 

         当然,还可以在search.awk文件利用BEGIN代码块写一些提示信息,这样便于运行程序的人能够看懂程序:

BEGIN {
    print "How many times 'VIOLATED' appears?"
}
/VIOLATED/ {++adder}   
END {                  
    print "'VIOLATED' appears " adder " times."
}

以上写在BEGIN代码块和END代码块的代码分别在初始化和所有输入数据处理完成后执行一次(仅一次)。

3.1.3 模式匹配

        我们可以使用模式匹配来使awk仅仅对部分的数据进行操作,而其他匹配不上的数据,awk将不作任何处理。在上述例子,awk会去匹配数据中的‘VIOLATED’正则表达式,匹配上才执行++adder。因此可以知道,awk匹配模式的语法如下:

/正则表达式/ {匹配后的操作}
  •         模式匹配
awk '/^$/ {print "This is an empty line."}' 1.rpt     #查看1.rpt文件中的空行数目。正则表达式^$匹配文件中的空行,当匹配上时,执行awk的print语句


awk '/VIOLATED/ {print $1}' 1.rpt       #使用正则表达式VIOLATED检索1.rpt文件中的每一行,当匹配上VIOLATED时,使用print语句打印出对应行的第一个字段
  •         多项模式匹配

        我们还可以在一个awk脚本中写出多个模式匹配代码,对匹配上的不同正则表达式的数据采用不同的处理: 


/VIOLATED/ {++violated}       #支持的第一个匹配
/MEET/     {++meet}           #支持的第二个匹配

END {                  
    print "'VIOLATED' appears " violated " times."
    print "'MEET' appears " meet " times."
}

3.2 数组与变量

3.2.1 变量

        awk中有两种变量:用户自定义变量内建变量

        在上文中,使用adder/violated/meet变量来统计VIOLATED/MEET字符串出现的次数,此处的adder/violated/meet就是用户自定义变量(书上对应描述VIOLATED/MEET为用户自定义变量,感觉有点问题);同时在上文我们重定义FS为冒号(:),此处FS即为内建变量

        awk的变量使用不需要先声明,而是在第一次使用该变量的时候自动建立变量(所以前面可以直接使用adder/violated/meet)。awk的变量在建立时的初始值都是空字符串,但是当需要数值时,它会被视为0。也就是说,awk会自动将字符串转换为数值进行计算。

        awk变量必须以ASCII字母或下划线开始,然后选择性的街上字母、下划线及数字。如果用正则表达式来匹配变量名的话,awk的变量名必须匹配[A-Za-z_][A-Za-z_0-9]*。在长度上,awk的变量名没有限制。

        awk变量名称区分大小写,如you、You及YOU是三个完全不同的名称。因此,可以按照以下建议:局部变量小写,全局变量首字母大写,内建变量全部大写。

        以下为awk常用的内建变量:

awk的常用内建变量
变量说明
FILENAME当前输入文件的名称
FNR当前输入文件的记录
FS字段分隔符(支持正则表达式),默认为空格
NF当前记录的字段数
NR在工作(job)中的记录数
OFS输出字段分隔字符
ORS输出记录分隔字符(默认为“\n”)
RS输入记录分隔字符

3.2.2 数组

        awk中的数组命名遵循了与变量命名相同的惯例。。。。这部分内容还不太理解

3.2.3 环境变量

        awk支持直接对环境变量的访问,通过ENVIRON数组。

3.3 算数运算和运算符

        在awk中可以直接进行算术运算。

awk 'BEGIN {print "3+2=" 3+2}'           #执行结果:3+2=5

awk 'BEGIN {print "2^10=" 2^10}'         #2^10=1024

awk 'BEGIN {print "(3+2)*7" (3+2)*7}'    #(3+2)*7=35

        下面表格为awk支持的运算符:

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

        关于以上表格的一些解释:

        (1)条件表达式:条件表达式是利用某条件判断的结果来决定该返回哪个表达式。例如,为了实现max(x,y),可以写成 x>y?x:y。这种表达式的含义是判断x是否大于y,如果是则返回x,如果不是则返回y

        (2)*=运算符。例如:x*=y,效果相当于x=x×y

        (3)++运算符。例如:x++,相当于x=x+1

        我们可以利用其中一些运算符来写一个判断年份是闰年还是平年:如果年份能被4整除但是不能被100整除,或者年份能被400整除,这两种情况的年份为闰年;其他则为平年。

        现year.text中的内容如下:

1987
2008
3000
2000
2012
1200
1300

        判断平闰年的leap.awk脚本内容:

BEGIN {
    print "Pick leap years:"
}
{
    year = $1                #将第一列内容赋值给year;同时awk不要求先声明变量,所以这里可以直接使用
    if ((year %4 == 0 && year %100 != 0) || year %400 == 0)       
        print year " is a leap year."
    else 
        print year " is not a leap year."
}

        使用awk调用leap.awk脚本,附执行结果:

awk -f leap.awk year.text

#执行结果
Pick leap years:
1987 is not a leap year.
2008 is a leap year.
3000 is not a leap year.
2000 is a leap year.
2012 is a leap year.
1200 is a leap year.
1300 is not a leap year.

3.4 判断与循环

     awk中的条件语句主要有if/else语句,循环有for和while。(主要是书写格式)

3.4.1 if语句

{
    if (expression) {
        statement;statement;...
    }
}

3.4.2 if/else语句

{
    if (expression) {
        statement;statement;...
    }
    else {
    statement;statement;...
    }
}

3.4.3 if/else else if语句

{
    if (expression) {
        statement;statement;...
    }
    else if  (expression) {
        statement;statement;...
    }
    else if  (expression) {
        statement;statement;...
    }
    else {
    statement;statement;...
    }
}

3.4.4 while循环

While (condition) {
action
}

#举例,让某个循环执行4次
i = 4
while (i >=1) {
print $i
i--
}

3.4.5 do/while循环

        awk的do...while循环,是在代码块结尾处对条件求值,而不像标准while循环那样在开始处求值。所以“do...while”循环永远都至少执行一次。

{
    count=1
    do {                #这一行将至少被执行一次
        print "haaaaaaa"
    } while (count !=1)        #此处的while判断如果不被满足,则退出循环
}

3.4.6 for循环

for (initial assignment;comparison;increment) {
    code block
}

        下面为一个例子及效果,x初始值为1,然后执行判断是否x<=4,判断为真则执行循环体,然后x++,对于x++的结果再判断是否x<=4。。。。。

for (x = 1 ;x <=4 ; x++) {     
    print "iteration",x
}


##打印结果如下:
iteration 1
iteration 2
iteration 3
iteration 4

3.4.7 break和continue

x=1
while (1) {
    print "haa" ,x
    if (x == 10) {
        break
    }
    x++
}

暂时够用 不学了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值