阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

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

185次阅读
没有评论

共计 4897 个字符,预计需要花费 13 分钟才能阅读完成。

试想一下,如果有 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/"

 


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

 

数据格式说明:

  • 上面是 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 年 ||| 姓名:张三 |||"

 


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

 

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

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

 


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

 

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 命令还是很有必要的,这样可以大大地降低你的工作量,提高工作的效率。

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-11/136787.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计4897字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中