天天看点

初学awk数组会遇到的几个常见问题

原题目:

处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

答案的详细讲解请参考:

<a href="http://lidao.blog.51cto.com/3388056/1912219" target="_blank">http://lidao.blog.51cto.com/3388056/1912219</a>

文件内容:

<code>http:</code><code>//www</code><code>.etiantian.org</code><code>/index</code><code>.html</code>

<code>http:</code><code>//www</code><code>.etiantian.org</code><code>/1</code><code>.html</code>

<code>http:</code><code>//post</code><code>.etiantian.org</code><code>/index</code><code>.html</code>

<code>http:</code><code>//mp3</code><code>.etiantian.org</code><code>/index</code><code>.html</code>

<code>http:</code><code>//www</code><code>.etiantian.org</code><code>/3</code><code>.html</code>

要求结果:

<code>mp3.etiantian.org 1</code>

<code>post.etiantian.org 2</code>

<code>www.etiantian.org 3</code>

答案:

<code>awk</code> <code>-F </code><code>"/+"</code> <code>'{hotel[$2]++}END{for(pol in hotel) print pol,hotel[pol]}'</code> <code>url.txt|</code><code>sort</code> <code>-rnk2</code>

有的小伙伴初学awk数组会有下面几个疑问。

为何要使用awk数组。

为何要使用$2作为房间号码。

我们结合这道题来看一下。

首先明确我们的目标,我们要什么结果?

www 出现了几次

mp3 出现了几次

post 出现了几次

第一个里程碑-简单容易理解的方法:

如果出现www则用a记录下www的重复数量,如果mp3出现则用b记录下mp3的重复数量,如果出现post则通过c记录下post的重复数量。

答案如下:

<code>[root@oldboy32-vm1files]</code><code>#awk -F "[/]+"'$2~/www/{a++}$2~/mp3/{b++}$2~/post/{c++}END{print"www:"a,"mp3:"b,"post:"c}' url.txt</code>

演示过程:

<code> </code><code>[root@showawkfile]</code><code>#  awk -F "[/]+"'$2~/www/{a++}$2~/mp3/{b++}$2~/post/{c++}END{print"www:"a,"mp3:"b,"post:"c}' url.txt</code>

<code>www:3 mp3:1 post:2</code>

虽然这样很容易理解,因为这里只有三种域名www,post,mp3的,一般工作上会有很多个域名,你就会疯了。

所以我们想要一个方法,一个东西(一个名字)可以装下这三种情况,并且互相不影响。

这个东西就是我们说的数组(酒店),这三个情况就是我们说的数组里面的元素(酒店房间)。

第二个里程碑-简单实用awk数组

还是刚才的思路,分三种情况,把不同的情况,这次是放入酒店的三个房间中。

<code>[root@show awkfile]</code><code>#awk -F "[/]+" '$2~/www/{h["www"]++}$2~/mp3/{h["mp3"]++}$2~/post/{h["post"]++}END{printh["www"],h["mp3"],h["post"]}' url.txt</code>

<code>3 1 2</code>

 提示:awk数组如果自己指定房间名字(数组元素名字),切记一定要加上双引号。否则awk会认为这是一个变量。

<code>[root@show awkfile]</code><code>#awk 'BEGIN{h[www]=1;h[bbs]=2;print h[www],h[bbs]}'</code>

<code>2 2</code>

<code>[root@show awkfile]</code><code>#awk 'BEGIN{h["www"]=1;h["bbs"]=2;printh["www"],h["bbs"]}'</code>

<code>1 2</code>

上面的例子就是如果不加上双引号,awk会认为是变量。

第三个里程碑-对号入座

还是很麻烦怎么解决呢?

有什么方法让遇到相同的内容就进入相同的房间吗?

如果遇到www自动进入www房间

如果遇到MP3自动进入MP3房间

如果遇到post自动进入post房间

可以的,思考一下我们如何通过awk得到www或mp3或post的呢?

他们都是第二列!awk中可以用$2表示。

所以,这个数组就可以写为。

h[$2]++即可,自动对号入座,对号入座后进行自加的操作(自动加1)。

<code>[root@show awkfile]</code><code>#awk -F "[/.]+" '{h[$2]++;print h["www"]}' url.txt</code>

<code>1</code>

<code>2</code>

<code>3</code>

<code>[root@show awkfile]</code><code>#awk -F "[/.]+" '{h[$2]++;print"www:"h["www"],"mp3:"h["mp3"],"post:"h["post"]}'url.txt</code>

<code>www:1 mp3: post:</code>

<code>www:2 mp3: post:</code>

<code>www:2 mp3: post:1</code>

<code>www:2 mp3:1 post:1</code>

<code>www:3 mp3:1 post:1</code>

<code>这样虽然可以看到我们想要的结果,但是也显示出了执行过程,我们只想要结果呀!</code>

第四个里程碑-输出结果

只要最后的结果可以通过END模式来解决。

<code>[root@show awkfile]</code><code>#awk -F "[/.]+" '{h[$2]++}END{print"www:"h["www"],"mp3:"h["mp3"],"post:"h["post"]}'url.txt</code>

这是一个房间一个房间的把内容显示出来,还是那句话当房间很多很多的时候,你又疯了。

awk自然有解决这个问题的方法,专用的循环。

<code>[root@show awkfile]</code><code>#awk -F "[/.]+" '{h[$2]++}END{for(pol in h)print pol,h[pol]}' url.txt</code>

<code>www 3</code>

<code>mp3 1</code>

<code>post 2</code>

到此我们又重新理解了一次awk数组。回顾下开始我们的问题。

他可以进行比较复杂的计算,当然也可以完成我们最常用的统计(去重)。

如果不用$2,作为房间号码,我们就需要手动来指定房间,这将是个噩梦。

$2正好可以表示www,mp3,post这几个内容。当然也涉及到了之前的知识,选择合适的刀,切出你想要的东西。

重新看下,hotel[$2]++是如何执行的,请看下图。

<a href="https://s3.51cto.com/wyfs02/M00/92/3F/wKiom1j9piqyAjPYAAKAbD6GgNs208.png" target="_blank"></a>

相关博客内容:

awk数组进行统计计数(去重)

awk数组进行累加(计算总和)

<a href="http://lidao.blog.51cto.com/3388056/1914563" target="_blank">http://lidao.blog.51cto.com/3388056/1914563</a>

本文转自 李导 51CTO博客,原文链接:http://blog.51cto.com/lidao/1918859

继续阅读