首页 > 学院 > 开发设计 > 正文

第14章 使用awk处理文本

2019-11-08 18:21:49
字体:
来源:转载
供稿:网友

1.     awk如何工作

awk和流编辑器sed在工作原理和用法上有很多类似之处,它们都是检查输入数据中的行是否匹配指定的模式,如果匹配成功就对匹配的行执行相应的操作,重复这个过程指导所有的输入数据都被处理完,因此awk和sed都是面向数据流的工具。此外,awk和sed的相似之处还体现在两者使用的语法式很类似,都是使用正则表达式匹配来确定要操作的行。与sed不同的是,awk执行的操作要写在模式后面的花括号{}中。

 

案例1:显示出系统中某个特定用户(如root用户)的用户名、用户ID以及主目录。

#提取passwd文件中某一行的三个字段

$awk –F: ‘/^root:/{PRint $1,$3,$6;}’/etc/passwd

root 0 /root

解析:/etc/passwd文件的各个字段是由冒号隔开,而awk的默认分隔符是空格,所以通过命令行选项-F:来指定;$1,$3,$6是指第一、三、六字段;

 

案例2:输出系统中所有用户的用户名及相应的用户ID的表格,并在表格的第一行为这两列数据添加标题。

具体代码实现如下[user.awk]:

#在主循环开始以前打印标题,使下面的数据的含义更加明确

print title to clarify the following databefore main loop begin

BEGIN {

   printf "%-15s%s/n","USERNAME","UID";

         printf"--------------/n";

}

 

#主循环开始运行

#从/etc/passwd文件中提取用户名和UID

{

   printf "%-15s%s/n",$1,$3;

}

#通过选项-f指定要运行的awk程序

$awk –F: -f user.awk  /etc/passwd

 

案例3:如何显示出当前系统中所有用户ID大于等于1000的用户?

#使用比较表达式,而不是模式匹配

$awk –F: ‘$3>=1000{ printf “User:%-15sUID:%s/n”,$1,$3;}’ /etc/passwd

 

格式:

expression { actions; }

 

当有多高表达式时,使用逻辑与&&和逻辑或||把多个表达式连接在一起构成更复杂的表达式,如搜索当前系统中所有使用bash和C Shell的用户:

$awk –F: ‘($7==”/bin/bash”)|| ($7==”/bin/csh”) { printf “User:%-15sUID:%-15sShell:%s/n”,$1,$3,$7; }’/etc/passwd

 

案例4:

2.     使用变量

awk 程序中的变量和Shell脚本中的变量很类似,都是用来存储一个值的。通过在awk程序中定义变量,我们可以更好地控制awk如何处理数据。处理用户自定义的变量以外,awk还预定义了一些内建变量,通过这些变量我们可以得到很多有用的信息。

总结awk常用的内建变量:

内建变量

描述

FILENAME

awk当前读取数据的文件,如果从标准输入中读取数据,变量的值为横杠-,在BEGIN规则中变量为空

FNR

当前文件中的当前行的行号,每读一行数据,它读值就会加1,在读取一个新文件时会被设置为0

NR

所处理的所有记录的个数。每一个新行被读,它的值就会自动加1

FS

输入行的字符分隔符,默认值为空格,可以通过命令行选项-F指定

NF

当前记录中所包含的字段个数,每次读入一个新的记录,它的值都会被重现设置

OFS

输出时的字段分隔符,默认是一个空格

ORS

输出时的记录分隔符,默认是换行符

RS

输入时的记录分隔符,默认是换行符

 

案例2:写一个脚本来统计文件中的总行数,空白行的行数及注释行的行数。

#!/bin/bash#本脚本需要至少一个命令行参数if [ "$#" -eq 0 ]then     echo "Usage;"    echo -e "/t'basename $0' [ FILE ]...."    exit 1fi #处理每一个命令行参数for FILE in "$@";do     #只有当文件是一个可读的文件,并且是一个含有数据的普通文件时才能被本脚本处理    if [ -f "$FILE" ]  && [ -r "$FILE" ] && [ -s "$FILE" ]    then        echo "$FILE:"        awk '            #统计所有的行数            /.*/{ total_lines += 1; }            #正则表达式/.*/匹配所有行,其中点代表一个任意的字符,而星号表示0个或任意个的星号前面的字符            #统计所有的空行数            /^ *$/{ empty_lines += 1; next; }            #正则表达式/^ *$/表示开头任意个空格,以$结尾            #统计所有的注释行行数            /^ *#.*$/{ comment_lines += 1; }            #正则表达式/^ *#.*$/表示#前可能有空格,最后以$结尾            #在主循环结束后输出结果            END {                 printf "/tTotal Lines:%s/t/t",total_lines;                 printf "Empty Lines:%s/t/t",empty_line;                 printf "Comment Lines:%s/n",comment_lines;            }        ' "$FILE"    else        echo "$FILE can not be handled!"    fidoneecho "Done."exit 0

案例3:如何打印/etc/passwd文件中的偶数行?

#!/bin/bashawk '    BEGIN {    #在主循环开始以前制定分隔符为冒号    FS=":";    }    #通过表达式匹配所有的偶数行,awk内建变量NR来实现    NR%2 == 0 {    print NR,$0;    }' /etc/passwdexit 0

案例4:如何处理多行记录中提取开发者的姓名和E-mail地址?

#!/bin/bashawk '    BEGIN {    # 设置分隔符为换行符/n    FS="/n";    #设置输入记录分隔符为空字符串    RS="";    #设置输出字段分隔符为换行符    OFS="/N"    #设置输出记录分隔符为两个换行符    ORS="/n/n"    #打印标题    print "The developers of linux Kernel:"    print "(N)name,(E)email"    print "---------------"    }    #使用正则表达式^N过滤所有无关数据,只对以字母N起始的记录块进行处理    /^N/ {    print $1,$2;    }' CREDITSexit 0

案例5:在上一例子中,我们提取出开发者的姓名和E-mail地址,如果希望得到每一个开发者的姓,也即名字字符串中的最后一个字段,应该怎么做呢?

#!/bin/bashawk '    BEGIN {    # 设置分隔符为换行符/n    FS="/n";    #设置输入记录分隔符为空字符串    RS="";    #设置输出字段分隔符为换行符    OFS="/N"    #设置输出记录分隔符为两个换行符    ORS="/n/n"    #打印标题    print "The developers of Linux Kernel:"    print "(N)name,(E)email"    print "---------------"    }    #使用正则表达式^N过滤所有无关数据,只对以字母N起始的记录块进行处理    /^N/ {        #输出以字母N起始的开发者的全名    print $1;    }#第一个awk程序的处理结果会继续发送第二个awk程序进行处理' CREDITS|awk '    BEGIN {        print "The Last Name of Developers:"        print "--------------------"    }    /^N/{        #打印行号和最后一个字段,NF表示字段个数,$NF表示最后一个字段        print NR,$NF;    }'exit 0

案例6:awk不能直接读取到shell变量,可通过命令行创建awk变量的方式把shell变量的值传递到awk程序中。

格式:

#使用环节变量定义awk变量

awk ‘script’ variable1=VALUE1variable2=VALUE2…files…

3.     控制语句

在awk程序中还可以使用控制语句,包括if语句、while语句、for语句和do-while语句。

4.     使用函数

awk中的函数分内建函数和自定义函数。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表