没想到 Shell 命令竟然还能这么玩?| Shell 玩转大数据分析

2024-04-13 04:48

本文主要是介绍没想到 Shell 命令竟然还能这么玩?| Shell 玩转大数据分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方蓝色字体,关注我 ——

一个在阿里云打工的清华学渣!

关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。公众号后台回复关键字 “1024” 获取程序员大厂面试指南。

图by: 石头

前奏

上周末团建了,没来得及肝文。跟同事们一起自驾去了秦皇岛阿那亚,吃吃烧烤,玩玩德扑,吹吹海风,很是惬意~ 

还学了一款新桌游 —— 阿瓦隆,很有意思,不知道你玩过没? 期间自己还闹了个大乌龙,这让我明白了一个道理:类似这种需要 “隐藏自己真实身份”的推理游戏的秘诀就是彻底忘记自己的身份,不仅能骗过“敌人”,还能让“队友”,甚至让拥有 “上帝视角”的“法官” 也懵逼到“怀疑人生”。

另外,本部门最近急招P6/P7技术岗,热烈欢迎感兴趣的同学联系我啊,下次团建咱们一起去,一起来玩德州扑克,我们都很菜的,很容易就能赢咱们。

分享几张本人拍的图片给大家(技术挫了点,大家将就看看)。

正文开始

在前面的这篇文章中 —— 优秀的程序员是如何利用工具来提升工作效率的?,石头介绍了可以提高程序猿工作效率的一些软件和工具及相关配置。文中提到了, 程序猿应该了解一些常见的命令行工具来提高效率。

本文是一个命令行工具的综合应用,将用一个具体的例子来阐述如何用 Shell 来进行高效地数据统计和分析。最近北京又开始了新一批积分落户的填报工作,恰好这篇文章用 shell 来对首批北京积分落户同学进行 "大数据"分析。

现如今到处都是各种"大数据",本文分析对象也就是首批积分落户的6000多条数据而已,显然不能算什么大数据。

印象中,我记得当初该官网的这6000多条数据也是一次性就能wget下来的(后端估计没做限制,可能稍微调整下接口的分页参数之类不需要严格按照各种分页多次下载)。(注:本文旧文重新整理发送。)

问题描述

输入是 json数据,格式化之后的 json 数据主题结构如下所示,rows为数组,数组中元素所代表的 object 即描述了获得北京户口的同学的各种属性:例如分数、排名、身份证号(后四位打码了)、公司等等信息。为了方便大家练习对数据进行试验,我将文中的数据附在这里(https://www.tanglei.name/resources/use-shell-to-analysis-the-first-people-of-getting-residence-of-beijing-by-score/jifenluohu.json.gz)。

"rows": [
{"id": 62981,"idCard": "32092219721222****","idCardSHA": "9ef70bde894959a4e4a1d1b2b9592b470294f9e4012a8cf480319665d1a7c1c6","insertTime": 1539518353000,"integralQualified": 1,"internetAnnual": {"annual": 2018,"id": 43,"insertTime": 1539518353000,"publicityEnd": 1540224000000,"publicityStart": 1539591600000,"publishResultEndDate": 1541679300000,"publishResultStartDate": 1539591600000,"publishResultStatus": 1,"score": 90.75,"status": 1},"md5Code": "54e9ff7ce0b004f7141b157f8afc66db","name": "杨效丰","pxid": 1,"ranking": 1,"s1": 51,"s10": 0,"s2": 12.59,"s3": 15,"s4": 0,"s5": 4,"s6": 0,"s7": 20,"s8": 20,"s9": 0,"score": 122.59,"unit": "北京利德华福电气技术有限公司"
},

拿到这个文件,比如希望你用最快的方法获得以下信息,你将会怎么做?

  • 获取取得户口名额最多的top10公司

  • 获取取得户口名额的人中姓氏最多的

  • 获取户口名字中叫啥名最流行

  • 获取年龄分布

  • 获取取得户口的同学户籍地top10

  • 生肖/星座/生日...

当然,方法有很多,比如熟悉各种编程语言的,例如 python, php, java 等等写个简单的脚本程序,也能比较快获取答案。或者把相应的数据提取出来,放到 excel 中也可以。

如果你对 Shell 很熟悉,那真的是分分钟,应该是秒秒钟就能获取答案。就算用 Shell 来实现,不同的人可能也有不同的写法,后面我就列举其中的一种来解决这些问题。

本文不对 Shell 具体每个命令做过多的解释,不熟悉的同学可以直接 man $cmd 或者 $cmd --help 等等查看。

之前我也写过一篇名叫 Shell 助力开发效率提升 的文章,算是给常用的命令的常用参数做了一个解释和示例,有兴趣的同学可以前往查阅。

问题解答

获取取得户口名额最多的top10公司

看看想通过积分落户,最好是进哪些公司,哈哈。

"unit": "北京利德华福电气技术有限公司"

先通过 grep 得到包含公司名字的一行,然后通过 ":" 分割 cut 取第2列得到公司名字,对结果进行sort排序进行去重uniq统计得到重复次数,次时结果为重复次数 公司名,再对第一列-k 1重复数字进行按照数字排序逆序-nr 即 sort -nr -k 1,最后取结果的前10行 head -n 10

➜  积分落户  > grep 'unit' jifenluohu.json| cut -f2 -d: | sort | uniq -c | sort -nr -k 1 | head -n 10137  "北京华为数字技术有限公司"73  "中央电视台"57  "北京首钢建设集团有限公司"55  "百度在线网络技术(北京)有限公司"48  "联想(北京)有限公司"40  "北京外企人力资源服务有限公司"40  "中国民生银行股份有限公司"39  "国际商业机器(中国)投资有限公司"29  "中国国际技术智力合作有限公司"27  "华为技术有限公司北京研究所"

获取取得户口名额的人中姓氏最多的

看看想通过积分落户,最好是姓啥,哈哈。

"name": "杨效丰",

套路跟之前差不多的,我这边就不特别指出了。

下面shell实际上是取到这行后,将真正表示名字之前的所有字符都删除,就只剩下名字开头了,取行首第一个字符cut -c 1即得到姓,再按照之前的套路就能拿到了。

其实用什么sed替换冗余的字符都是多余的,因为json的格式都是良好的,可以直接通过 cut -c ? 取姓这个字符即可。

也不用挨个去数到底是第几个字符,直接 copy出来,然后 echo -n $paste | wc -c 就能数到第几个字符了。

看结果还是姓 "张, 王" 之类的最有戏。????

# 或者 grep '"name":' jifenluohu.json| sed 's|"name": "||g' | sed 's|[[:space:]]||g' | cut -c 1 | sort | uniq -c | sort -nr -k 1 | head -n 10
➜  积分落户  > grep '"name":' jifenluohu.json| sed 's|"name": "||g' | sed 's| ||g' | cut -c 1 | sort | uniq -c | sort -nr -k 1 | head -n 10541 张531 王462 李376 刘205 陈193 杨166 赵132 孙95 郭95 徐

获取户口名字中叫啥名最流行

套路差不多,不做过多解释了。

➜  积分落户  > grep '"name":' jifenluohu.json| sed 's|"name": "||g' | sed 's|[[:space:]]||g' | cut -c 2-4 | sort | uniq -c | sort -nr -k 1 | head -n 1051 伟",39 静",38 涛",36 勇",36 军",32 敏",31 颖",30 鹏",28 杰",28 峰",
# 取名字, 必须包含2个字
➜  积分落户  > grep '"name":' jifenluohu.json| sed 's|"name": "||g' | sed 's|[[:space:]]||g' | cut -c 2-3 | sed  '/"/d' | sort | uniq -c | sort -nr -k 1 | head -n 1019 海涛19 晓东12 志强11 海燕11 永强11 建华10 雪梅9 海龙9 丽娜8 洪涛

作为码农,必须得养成对自己得到结果进行自测的习惯,所以如果对自己的结果不够自信,可以正向去计算一下最终的结果。

例如可以简单grep一下进行验证,叫 "海涛" 的是不是19个。

➜  积分落户  > grep '海涛' jifenluohu.json | wc -l19  

获取年龄分布

思路是截取身份证中号码中代表出生年的4位数,然后拿当前年份2019减出生年得到年龄,后面的套路又一样了。

bc 一个简单的计算器程序,了解下?

➜  shell-train  > echo "3+2-5/5" | bc
4
➜  shell-train  > echo "3.141592*5-4" | bc
11.707960
#思路1: `cut -c 9-12` 获取出生年, 拼接表达式 `2019-出生年` 得到年龄.
➜  积分落户  > grep '"idCard":' jifenluohu.json| cut -f2 -d: | cut -c 9-12 | xargs -n1 echo 2019 -|bc | sort | uniq -c3 3413 3539 36109 37162 38302 39507 40773 41799 42813 43757 44586 45507 46378 47238 484 499 501 514 523 532 545 551 561 581 591 601 61

awk 是个好东西, 多练练.

# 拿到出生年后, 直接通过 awk 计算结果输出
➜  积分落户  > grep '"idCard":' jifenluohu.json| cut -f2 -d: | cut -c 9-12 |awk '{print 2019-$1}' | sort | uniq -c3 3413 3539 36109 37162 38302 39507 40773 41799 42813 43757 44586 45507 46378 47238 484 499 501 514 523 532 545 551 561 581 591 601 61   

获取取得户口的同学户籍地top10

有时候,我们在写Shell的时候,为了debug方便,可能会将一些中间结果缓存到文件中,后续以该文件为基础进行后续的计算。

比如先拿到top10的身份证中代表的户籍地的四位编码,这里需要借助另外的一个表示身份证户籍地的编码来进行对应。

借此机会解释下 join 这个命令。

# 身份证前4位为例, 拿到户籍地
grep '"idCard":' jifenluohu.json| cut -f2 -d: | cut -c 3-6 | sort | uniq -c | sort -nr -k 1 >topcity.code
# 城市列表
➜  积分落户  > more city.csv
11,北京市
1101,北京市市辖区
110101,北京市东城区
110102,北京市西城区
110103,北京市崇文区
110104,北京市宣武区
110105,北京市朝阳区
# grep -E '^[0-9]{4},' city.csv | sed 's|,| |g' > city.code4
➜ shell-train  > head -n 2 city.code4
1101 北京市市辖区
1102 北京市市辖县
➜ shell-train  > head -n 2 topcity.code197 1201156 1302
➜ shell-train  > join
usage: join [-a fileno | -v fileno ] [-e string] [-1 field] [-2 field][-o list] [-t char] file1 file2

其实,join 就类似sql中的 ...inner join ...on ..., -t 分隔符,默认为空格或tab

# 未排序, 所以没有将所有的导出(join需要排序)
➜ shell-train  > join -1 1 -2 2 city.code4 topcity.code
1201 天津市市辖区 197
1302 河北省唐山市 156
2301 黑龙江哈尔滨市 123
4201 湖北省武汉市 118
6101 陕西省西安市 100
6201 甘肃省兰州市 59
6501 新疆乌鲁木齐市 29
6523 新疆昌吉回族自治州 11

一定需要将结果输出到文件,然后再进行吗?

其实也不一定。用管道的方式 | 可以将上一个命令的输出结果作为下一个命令的输入,可以通过 <(command) 的方式,将command 的输出作为一个文件输入。

# 需要排序
➜ shell-train  > join -1 1 -2 2 city.code4 <(head -n 10 topcity.code | sort -k 2)
1201 天津市市辖区 197
1301 河北省石家庄市 114
1302 河北省唐山市 156
1324 河北省保定地区 103
1501 内蒙古呼和浩特市 88
2101 辽宁省沈阳市 109
2201 吉林省长春市 113
2301 黑龙江哈尔滨市 123
4201 湖北省武汉市 118
6101 陕西省西安市 100

举个例子paste用来将两个文件按列合并在一起:

➜  shell-train  > cat paste.f1
hello, i am
world, you are
➜  shell-train  > cat paste.f2
tanglei, wechat is: tangleithu
?, hahaha
➜  shell-train  > paste paste.f1 paste.f2
hello, i am tanglei, wechat is: tangleithu
world, you are ?, hahaha

以上用paste将两个文件合并在一起了,实际上通过 <(cmd)的方式,可以不借助外部文件也能做到。

方法如下:

➜  shell-train  > paste <(echo "hello, i am \nworld, you are") <(echo "tanglei, wechat is: tangleithu\n?, hahaha")
hello, i am  tanglei, wechat is: tangleithu
world, you are ?, hahaha

其他的任务交给你了

这里就不重复多讲了,剩下的问题,要不你动手试试,比如看看生日最多的?

再试试获取 生肖/星座 最多的top10。

有任何疑问,欢迎留言交流参与交流讨论。

后记

觉得本号分享的文章有价值,记得添加星标哦。周更很累,不要白 piao,需要来点正反馈,安排个 “一键三连”(点赞、在看、分享)如何????? 这将是我持续输出优质文章的最强动力。

关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader。用不同的视角分享高质量技术文章,以每篇文章都让人有收获为目的,欢迎关注,交流和指导!

公众号后台回复关键字 “1024” 获取程序员大厂面试指南。

推 荐 阅 读

快快加入我们——“阿里云-ECS/神龙计算平台” 招人啦
面试官:会玩牌吧?给我讲讲洗牌算法和它的应用场景吧!

面了 7 轮 Google,最终还是逃不脱被挂的命运

从一道面试题谈谈一线大厂码农应该具备的基本能力

- 欢迎加入互联网大厂内推群 & 技术交流群 -

这篇关于没想到 Shell 命令竟然还能这么玩?| Shell 玩转大数据分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/899177

相关文章

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

PHP执行php.exe -v命令报错的解决方案

《PHP执行php.exe-v命令报错的解决方案》:本文主要介绍PHP执行php.exe-v命令报错的解决方案,文中通过图文讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录执行phpandroid.exe -v命令报错解决方案执行php.exe -v命令报错-PHP War

CentOS系统使用yum命令报错问题及解决

《CentOS系统使用yum命令报错问题及解决》文章主要讲述了在CentOS系统中使用yum命令时遇到的错误,并提供了个人解决方法,希望对大家有所帮助,并鼓励大家支持脚本之家... 目录Centos系统使用yum命令报错找到文件替换源文件为总结CentOS系统使用yum命令报错http://www.cppc

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

30常用 Maven 命令

Maven 是一个强大的项目管理和构建工具,它广泛用于 Java 项目的依赖管理、构建流程和插件集成。Maven 的命令行工具提供了大量的命令来帮助开发人员管理项目的生命周期、依赖和插件。以下是 常用 Maven 命令的使用场景及其详细解释。 1. mvn clean 使用场景:清理项目的生成目录,通常用于删除项目中自动生成的文件(如 target/ 目录)。共性规律:清理操作

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

linux 判断某个命令是否安装

linux 判断某个命令是否安装 if ! [ -x "$(command -v git)" ]; thenecho 'Error: git is not installed.' >&2exit 1fi

jenkins 插件执行shell命令时,提示“Command not found”处理方法

首先提示找不到“Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具执行shell命令是可以执行。奇怪的就是通过jenkinsSSH插件无法执行,经一番折腾各种搜索发现是jenkins没有加载/etc/profile导致。 【解决办法】: 需要在jenkins调用shell脚