10G数据不用框架快速去重

试想一下,如果有10G数据,或者更多;怎么才能够快速地去重呢?你会说将数据导入到数据库(mysql等)进行去重,或者用java写个程序进行去重,或者用Hadoop进行处理。如果是大量的数据要写入数据库也不是一件容易的事情,首先你需要开发一个程序将数据写入数据库,然后再用数据库的select distinct或者group by进行去重。如果是一次性的工作,这种方式显得就比较笨拙了。那么有没有更好的办法呢?下面记录一下我是怎么从10G数据里面迅速去重的。这里采用shell脚本的方式进行处理。

说明

  • 这10G数据分布在七八个文件中

  • 文件编码格式为gb2312

  • 数据格式:

"ID","已采","已发","内容","PageUrl"
"1","1","1","====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||","http://www.xxx.com/"
"1","1","1","====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||","http://www.xxx.com/"
"1","1","1","====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||","http://www.xxx.com/"



数据格式说明:

  • 上面是3行数据
  • 每行都是5个field
  • 每个field间用“,”隔开
  • 而需要的内容在第4个field(也就是内容这个field)
  • 内容field间会员用“ ==================== ”隔开
    要达到的效果:将会员信息提取出来并去重

实现思路和测试

1.由于文件编码是gb2312编码,所以第一步是将文件编码转成utf-8编码

iconv -c -f gb2312 -t utf-8 test.txt > test2.txt

这里我们用linux系统自带的iconv命令进行转换,-c的意思是将无法识别的字符直接忽略掉

2、获取会员信息,由于是第4个field,因而我们只需要获取第四个field即可,这里采用awk命令获取

awk 'BEGIN{ FS=",";}{ print $4 }' test2.txt > test_menber.txt

awk指定分隔符的方法为FS=”,”,运行后的结果如下

vi test_menber.txt
"内容"
"====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"
"====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"
"====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||====================会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"

这里已经获取到了会员的信息;但是一行有多个会员的信息,而个数又是不固定的。因此下面是想办法一行显示一个会员

3、一行显示一个会员

由于会员信息间通过“====================”分割,要实现一行显示一个会员只需要将“====================”替换成换行即可。

sed -i "s/====================/\n/g" test_menber.txt

查看test_menber.txt的内容

vi test_menber.txt 
  1 "内容"
  2 "
  3 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
  4 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
  5 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
  6 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"
  7 "
  8 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
  9 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
     10 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
     11 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"
     12 "
     13 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
     14 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
     15 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||
     16 会员名:鬼脚七||||||||||||||||||会员等级:军长第5年|||姓名:张三 |||"



4、替换掉其他字符“””、空行和“|||”

#将“"”替换成空字符串
sed -i "s/\"//g" test_menber.txt
#删除空行
sed -i '/^$/d' test_menber.txt
#将分隔符|||换成@
sed -i "s/|||/@/g" test_menber.txt



5、根据会员名去重

sort -t $"@" -k 1,1 -su test_menber.txt >test_uniq.txt

-t可以指定分隔符,-k指定排序的field, -su表示稳定排序并去重

查看结果

[root@bogon yichen]# more test_uniq.txt 
会员名:鬼脚七@@@@@@会员等级:军长第5@姓名:张三 @
内容

思路和测试完成了,但是文件比较多,一个个文件去处理也比较麻烦。因而写个脚本去处理即可

脚本批量处理

1、转换文件编码

[root@bogon yichen]# vi iconv_shell.sh 
#!/bin/sh
if [ "$#" != "2" ]; then
echo "Usage: `basename $0` dir filter"
exit
fi
echo $1
for file in `find $1 -name "$2"`; do
echo "$file"
iconv -c -f gb2312 -t utf8 $file > ${file}_utf8

调用./iconv_shell.sh 目录 文件通配符,例如:

./iconv_shell.sh ./ "*txt"

此时生成的文件后缀为:.txt_utf8

2、提取会员信息

vi awk_filler.sh 
#!/bin/sh
if [ "$#" != "2" ]; then
echo "Usage: `basename $0` dir filter"
exit
fi
for file in `find $1 -name "$2"`; do
echo "$file"
awk 'BEGIN{ FS=",";}{ print $4 }' $file > ${file}_menber
done

调用

./awk_filler.sh ./ "*.txt_utf8"

此时生成的文件后缀为:.txt_utf8 _menber

3、替换“ ==================== ”、“””、“|||”和换行

vi sed_shell.sh 
#!/bin/sh
if [ "$#" != "2" ]; then
echo "Usage: `basename $0` dir filter"
exit
fi
for file in `find $1 -name "$2"`; do
echo "$file"
sed -i "s/====================/\n/g; s/\"//g; /^$/d; s/|||/@/g" $file
done

for file in `find $1 -name "$2"`; do
echo "$file"
sed -i "/^$/d" $file
done

sed支持多表达式:sed “表达式1;表达式2” filename,注意表达式之间用“;”号隔开。

调用:

sh ./sed_shell.sh ./ "*.txt_utf8_menber"

替换后的文件后缀仍为txt_utf8_menber

4、去重

vi uniq_shell.sh 
#!/bin/sh
if [ "$#" != "2" ]; then
echo "Usage: `basename $0` dir filter"
exit
fi
for file in `find $1 -name "$2"`; do
echo "$file"
sort -t $"@" -k 1,1 -su ${file} >${file}_uniq
done

调用:

sh ./uniq_shell.sh ./ "*.txt_utf8_menber"

最后生成去重后的文件后缀为txt_utf8_menber_uniq

其实也可以放在一个shell脚本里面完成,这里就不再阐述了。想想看10G的文件用几个简单的命令就完成了去重,可见linux的强大。所以说学几个简单的linux命令还是很有必要的,这样可以大大地降低你的工作量,提高工作的效率。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
课后作业 1. 简述zookeeper在HBase中的作用 2. 如何获取链接zookeeper的客户端的信息 3. 简述如何用zookeeper实现一个普通的一对多fifo队列 4. 使用伪代码简述mapreduce的流程和中间结果 其中input和output都是fileinputformat和fileoutputformat 5. 编写程序实现倒排索引 首先准备数据:1.txt,文件内容如下: The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-availability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-available service on top of a cluster of computers, each of which may be prone to failures. 文件2.txt的内容如下所示: In order to scale the name service horizontally, federation uses multiple independent Namenodes/Namespaces. The Namenodes are federated, that is, the Namenodes are independent and don’t require coordination with each other. The datanodes are used as common storage for blocks by all the Namenodes. Each datanode registers with all the Namenodes in the cluster. Datanodes send periodic heartbeats and block reports and handles commands from the Namenodes. 建立类似的文件,放入/test1文件夹下 要求处理结果为: The 1.txt n 2.txt n Apache 1.txt n 2.txt n 其中,n为某个单词在某个文件出现的次数,即,格式解释为:单词iterator<所在文件 出现次数>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值