还在为文本数据处理犯愁吗?看看这里(文末有彩蛋)!

服务端测试里面很重要的一项内容是性能测试。几乎每一个服务我们都要通过测试手段去评估它的性能指标:能支持多少用户同时访问、服务端响应时间、服务端资源占用等等。一般而言我们是通过性能测试的软件,比如LoadRunner,通过模拟多个客户端同时向服务端发送请求来进行测试的。而在构造这些请求时,通常会需要做一些文本处理的工作。

一个实际的场景:某天开发找到小编说需要对某个图片搜索的接口做压力测试。然后开发告诉我:“这有一个线上搜索请求的log数据,大概一百万条,100M左右,你在里面抽取个一两万条用作压测数据吧。” log数据的结构大概是这样:

还在为文本数据处理犯愁吗?看看这里(文末有彩蛋)!

我们需要做的是把第一列的部分数据抽取出来单独做成一个文件。

按说处理的方法很多,比如最容易想到的,Python写个脚本,读入文件,处理之后输出即可。但其实这并不是最好的解决方案。今天就和大家介绍一款服务端文本处理的强大工具——awk

一、什么是awk

AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。

说白了awk就是一个强大的文本处理工具。究竟怎么个强大法呢?我们看看文章开头提到的问题。如果该问题用awk去处理的话应该是怎样的呢?

 awk '{print $1 > "result.txt"}' searchIsHit_20170213.txt

是的,就只需要这一行代码即可搞定,应该是比写个小程序去处理文本简单多了。这行代码的作用是把searchIsHit_20170213.txt文件中的第一列输出到result.txt文件中。

二、awk基本用法

我们可以把awk的语法简单总结为:

awk '{pattern + action}'
# 或者这样
awk 'pattern {action}'

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。
以下就列举一些小编在平时测试工作中会用到的常见用法。

1.截取文件中固定的行(列)

如果你需要截取文件中固定的列,那么就用一行代码即可:

 awk '{print $n > "ResultFile"}' SourceFile

其中$n表示文件的第n列,从1开始。n=0表示该文件的所有列。
>是重定向输出符号,表示将内容输出到某个固定的文件中。

如果需要操作该文件的前XX行或者固定的某几行,该怎么做呢?awk提供了一个内置的参数:NR,表示已经读入的记录数(就是行数)。因此如果我们需要截取前10000行的内容,这样既可:

 awk 'NR<=10000 {print $1 > "result.txt"}' searchIsHit_20170213.txt

同样,我们截取第1000到2000行之间的数据时,可以这样搞:

 awk 'NR>1000&&NR<=2000 {print $1 > "result.txt"}' searchIsHit_20170213.txt

awk可以通过 -F 参数指定分割符。在上面的情况中,我们没有指定,默认是以空格作为分隔符。如果某个文件中的分隔符不是空格,比如“:”,这时候-F参数就派上用场了:

 awk -F ":"'{print $1 > "result.txt"}' searchIsHit_20170213.txt
2.进行匹配查找

实际的需求中,我们通常需要在log文件中筛选出包含某些关键字的行。这时候就需要用到匹配查找了。匹配查找中,~表示模式开始,/ /中间是待查找的模式。举个例子,在某个log文件中,需要找出所有包含”JudgingTime”字段的行,那么awk可以这样做:

 awk '$0~/JudgingTime/ {print $0 > "result.txt"}' test.log

除此之外,awk比较强大的地方在于它支持正则表达式的匹配。
举个例子,在某个文件中需要筛选出第一列是字母的所有行,可以这样做:

 awk '$1~/([a-zA-Z]+)/ {print $0 > "result.txt"}' test.log

只要把需要过滤的正则表达式写到模式里面即可。

3.awk内置属性和函数

awk内置了一些常用的属性和函数,便于我们去调用实现更强大的功能。一些常见的函数如下:

属性/函数 含义
length 长度
IGNORECASE 忽略大小写
split(string,array) 将指定的字符串切割成数组
substr(s,p) 返回字符串s中从第p个字符开始的后缀部分
substr(s,p,n) 返回字符串s中从第p个字符开始长度为n的后缀部分
match(a,b) 返回b在a中出现的位置,如果不包含则返回0
tolower(s)/toupper(s) 将字符串转为小写/大写

看几个例子:
i.匹配length长度小于某个值的所有行:

 awk 'length < 20 {print $0}' test.log

ii.忽略大小写匹配:

 awk '{IGNORECASE=1} $0~/abc/ {print $0}' test.log

上述命令可以把包含abc(大小写均可)的行输出出来。

iii.截取子串

awk 'length < 20 {print substr($0,3,2)}' test.log

如果log中某行长度小于20,上述命令可将该行从第三个字符开始长度为2的子串输出出来。

3.结语

awk是一个功能非常强大的文本处理工具。小编从自己做压力测试准备测试数据的角度出发,仅向大家说明了最简单最基础的知识,涵盖平时测试时会用到的一些方法。关于awk的高级用法,各位读者大神们可以自行研究。相信这肯定是一个可以提高工作效(逼)率(格)的工具。

4.文末彩蛋

经常关注我们公众号的读者朋友对搜狗铲子哥肯定非常熟悉吧?这次给大家留的彩蛋是铲子哥提出的一个小问题:

还在为文本数据处理犯愁吗?看看这里(文末有彩蛋)!

在一个log文件中,我们通过awk命令找出了所有包含“nnJudgingTime”的行,如上图。那么问题来了:
怎么提取出nnJudgingTime后面的值(数字)呢?

欢迎大家在留言区聊聊自己的想法,说不定铲子哥会有礼品送上哦~

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: