请用脚本语言 Shell完成如下功能:
给定URL 列表统计每个站点出现的 URL数
请用脚本语言 Shell完成如下功能,要求实现越简单越好:
1/ 给定URL 列表统计每个站点出现的 URL数
2/ 从一批url中grep出首页
3/ 从一批url中grep出目录页
4/ 从一批url中grep出日期页面
5/ 求两文件的交集、并集、差集
注:(1)必须使用bash script;(2)可以内嵌awk。
提供一个文本文件1(all.site),每行两列,格式为 site urlnum。
提供一个文本文件2(all.domain),每行一列,格式为 每行一个主域名
定义:主域名,如下:
news.sina.com.cn 主域为sina.com.cn
www.5yiso.cn 主域为5yiso.cn
apple.club.sohu.com 主域为sohu.com
要求计算:
(1)文件2中每个主域上在文件1中存在的站点数(文件1中站点不能保证无重复)和url数量总和
(2)站点上url数量超过所在主域上站点平均url数量的站点集合
如文件1为
hshlkm.yp.sina.net 234
www.sina.net 220
cmcy.hljeca.com 1
文件2为
sina.net
combuilders.org
则计算结果1为:
sina.net 2 454
combuilders.org 1 3
数据位置:zixia:/home/work/TraningData/statdomain/
*********************************************************************
*********************************************************************
comm 属于 diff 家族的命令, 相当于寻找两个字符串的最长公共子串. 在寻找前, 要对两个文件先排序. 然后diff内部哈希把一行字符变成一个整数, 再使用寻找最长公共子串的动态规划. 因此, 比较一个 m 长文件和一个 n 长文件的复杂度还是比较大. 读者有兴趣的可以阅读这篇论文[PS]. 其实我自己以前也用Comm, 但是不知道为什么, comm 求集合差集的效果不好. 即使排好了序, 有很多文件之间算差集还是做不对.
找两个文件的交集和差集是很普通的一个事情. 举个简单的例子, 我每周都去Google 音乐趋势抓歌曲名, 抓完了以后, 我要知道哪些是我需要下的新歌 (因为有的歌可能在榜好几个星期, 不需要重复下载). 假设我机器上存的歌曲是集合B, 新抓取了集合A. 假设这些集合这都用文件存着, 每行一个歌曲名. 任务就是计算 A-B, 也就是在集合A中而不在集合B 中的那些歌曲. 我长期的使用经验证明, comm 并不能准确的算出差集.
抓耳挠腮了好久, 想: 要是的确有这个需求, 又没这个现成的工具, 那么肯定一行脚本能写出来. 其实只要运用集合论知识一想就知道, 就是在A中把同时在 A和B 中出现的剔除了呗. 因此办法是, 把 两个B 集合和一个 A 文件放到一起成一个大文件(集合), 然后选取这个大集合中唯一的. 那么这个唯一的肯定就是只在A中不在B中的, 仔细想想就知道是对的. 所以, 方法是:
sort B B A | uniq -u
同理, 对称差是:
sort A B | uniq -u
为什么我不喜欢用 comm 呢, 因为comm 是对有序的列表做操作的, 如果对集合, sort 和 uniq 足矣. 可能车大虾说的 join 两个表就是这个了, 不过我觉得, 这个看上去可能更加容易写一点, 毕竟用 comm 的比用 sort 和 uniq 的少一点, 而且, 复杂度也低, 构造也巧妙, 这个多能显示良好的数学和计算机功底啊
Linux 不是玩具, 是提高工作效率的智慧的工具. 我越用越觉得缺少的只是想象力.
Update: Linux 下面解决问题从来就不止一种方法, 今天一个美国同事告诉我另一个方法求差集 A-B:
grep -F -f listb lista -v
那求交集可以用grep -F -f listb lista -v 了,呵呵.
=====
我原文当中好像就写了吧:
grep -F -f listb lista -v