正文开始于上一篇-优秀的程序员如何使用工具提高工作效率?,Stone介绍了一些可以提高程序员工作效率的软件、工具及相关配置。文中提到,程序员应该了解一些常用的命令行工具,以提高效率。本文是命令行工具的综合应用,将通过一个具体的例子来说明如何使用Shell进行高效的数据统计和分析。近日,北京启动了新一批积分登记工作。恰好本文用shell对北京首批积分制学生进行了“大数据”分析。如今,各种“大数据”无处不在,而本文分析的对象只是第一批入驻积分的6000多条数据,显然不能算大数据。印象中,记得官网6000多条数据也是可以一次性wget的(后端估计没有限制,可能会稍微调整一下接口的分页参数,还有无需严格按照各种分页多次下载)。(注:本文旧文整理发)问题描述输入为json数据。格式化后的json数据主体结构如下。rows是一个数组,数组中的元素所代表的对象描述了获得北京户口的学生。各种属性:如分数、名次、身份证号(后四位编码)、公司等信息。为了方便大家用数据练习实验,我在这里附上文章中的数据(https://www.tanglei.name/resources/use-shell-to-analysis-the-first-people-of-getting-北京住所-by-score/jifenluohu.json.gz)。"rows":[{"id":62981,"idCard":"32092219721222****","idCardSHA":"9ef70bde894959a4e4a1d1b2b9592b470294f9e4012a8cf480319665d1a7c1c6","insertTime":1539518353000,"integralQualified":1,"internetAnnual":{"“年度”:2018,“ID”:43,“插入时间”:1539518353000,“宣传结束”:1540224000000,“宣传开始”:1539591600000,“发布结果结束日期”:1541679300000,“发布结果开始日期”:1539591600000,“发布:1,”结果状态“: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,“分数“:122.59,"unit":"北京利德华福电气科技有限公司"},得到这个文件,比如,如果你想以最快的方式得到下面的信息,你会怎么做?获取注册账号最多的top10公司获取获取账号的人中姓氏最多的人,获取账号名中最流行的名字,获取年龄分布,获取top10的户籍地获得账号的同学,生肖/星座/生日……当然,方法有很多种,比如熟悉各种编程语言,比如python,php,java等,写一个简单的脚本程序,以及可以比较快的得到答案或者提取相应的数据,放到excel中。如果你熟悉Shell,真的需要几分钟,你应该可以在几秒钟内得到答案。即使是用Shell实现,不同的人也可能有不同的写法。稍后我将列出其中一个来解决这些问题。本文对Shell的各个具体命令不作过多解释。不熟悉的同学可以直接用man$cmd或者$cmd--help等查看。之前也写过一篇文章叫Shell帮助提高开发效率。是常用命令常用参数的解释和示例。有兴趣的同学可以去看看。问题解答获取获得账户最多的前10家公司。想积分入驻,看看哪些公司最好加入,哈哈。《单位》:《北京利德华福电气科技有限公司》先通过grep获取包含公司名称的行,然后用“:”分割cut从第二列获取公司名称,对结果进行排序去重uniq统计得到重复次数,第二个结果为重复次数的公司名称,然后将第一列-k1中重复的数字进行倒序排序-nr,即排序-nr-k1,最后取结果头的前10行-10.?积分落户>grep'unit'jifenluohu.json|cut-f2-d:|sort|uniq-c|sort-nr-k1|head-n10137《北京华为数字技术有限公司》73《CCTV》57》北京首钢建设集团有限公司《55》百度在线网络技术(北京)有限公司《48》联想(北京)有限公司《40》北京外企人力资源服务有限公司.《40》中国民生银行股份有限公司《39》国际商业机器(中国)投资有限公司《29》中国国际技术智力合作有限公司《27》华为技术有限公司北京研究院.,Ltd.”获取获得账号的人中姓氏最多的人。看你要不要通过积分结算。最好的姓氏是什么?,哈哈。"name":"杨晓峰",套路和之前一样,这里就不点了。下面的shell其实就是把这一行,删除了真名前的所有字符,只剩下名字的开头。取行首的第一个字符cut-c1得到姓氏,然后按照前面的套路就可以得到。其实任何用来替换多余字符的sed都是多余的,因为json的格式好,可以直接用cut-c?得到姓氏的特征。不用一个一个统计字符个数,直接复制出来,然后echo-n$paste|wc-c可以统计字符数。从结果来看,“张、王”之类的姓氏最有趣。??#或者grep'"name":'jifenluohu.json|sed's|"name":"||g'|sed's|[[:space:]]||g'|cut-c1|sort|uniq-c|sort-nr-k1|head-n10?点数解决>grep'"name":'jifenluohu.json|sed's|"name":"||g'|sed's|||g'|cut-c1|sort|uniq-c|sort-nr-k1|head-n10541张531王462李376刘205陈193杨166赵132孙95郭95旭不解释太多。?积分入驻>grep'"name":'jifenluohu.json|sed's|"name":"||g'|sed's|[[:space:]]||g'|cut-c2-4|sort|uniq-c|sort-nr-k1|head-n1051卫",39经",38道",36勇",36军",32民",31营",30彭",28杰",28丰",#名字必须包含2个字符?点数解决>grep'"name":'jifenluohu.json|sed's|"name":"||g'|sed's|[[:space:]]||g'|cut-c2-3|sed'/"/d'|sort|uniq-c|sort-nr-k1|head-n1019海涛19晓东12志强11海燕11永强11建华10雪梅9海龙9丽娜8洪涛,as一个coder,一定要养成对自己得到的结果进行自我测试的习惯,所以如果对自己的结果没有信心,可以积极地计算出最后的结果。比如可以简单的grep验证一下,是否有19人名为“海涛”??Integralsettlement>grep'海涛'jifenluohu.json|wc-l19Theideaof????obtainingtheagedistributionistointerceptthe4-digitnumberrepresentingtheyearofbirthintheIDcardnumber,andthensubtracttheyearofbirthfromthecurrentyear2019togettheage,andthefollowingroutinessame.bcAsimplecalculatorprogram,understand??shell-train>echo"3+2-5/5"|bc4?shell-train>echo"3.141592*5-4"|bc11.707960#Thought1:`cut-c9-12`togettheyearofbirth,concatenatetheexpression`2019-yearofbirth`togettheage.?Pointssettled>grep'"idCard":'jifenluohu.json|cut-f2-d:|cut-c9-12|xargs-n1echo2019-|bc|sort|uniq-c33413353936109371623830239507407734179942813437574458645507463784723848449950151452353254555156158159160161awk是个好东西,多练练.#拿到出生年后,直接通过awk计算结果输出?积分落户>grep'"idCard":'jifenluohu.json|cut-f2-d:|cut-c9-12|awk'{print2019-$1}'|sort|uniq-c33413353936109371623830239507407734179942813437574458645507463784723848449950151452353254555156158159160161获取取得户口的同学户籍地top10有时候,我们在写Shell的时候,为了debug方便,可能会将Someintermediateresultsarecachedinafile,andsubsequentcalculationsareperformedbasedonthefile.Forexample,firstgetthefour-digitcodeoftheplaceofresidencerepresentedinthetop10IDcard,andhereweneedtouseanothercodeindicatingtheplaceofresidenceoftheIDcardtocorrespond.Takethisopportunitytoexplainthejoincommand.#以身份证前4位为例,获取居住地grep'"idCard":'jifenluohu.json|cut-f2-d:|cut-c3-6|sort|uniq-c|sort-nr-k1>topcity.code#城市列表?积分落户>morecity.csv11,北京1101,北京市110101,北京东城区110102,北京西城区110103,北京崇文区110104,北京玄武区110105,北京朝阳区District#grep-E'^[0-9]{4},'city.csv|sed's|,||g'>city.code4?shell-train>head-n2city.code41101北京市城区1102北京市县?shell-train>head-n2topcity.code19712011561302?shell-train>joinusage:join[-afileno|-vfileno][-estring][-1field][-2field][-olist][-tchar]file1file2其实join类似于...innerjoin...on...insql,-t分隔符,默认为空格或tab。#Unsorted,所以不是全部输出(join需要排序)?shell-train>join-11-22city.code4topcity.code1201天津市区1971302河北省唐山市1562301黑龙江哈尔滨市1234201湖北省武汉市1186101陕西省西安1006201甘肃省兰州市596501新疆乌鲁木齐市296523新疆昌吉回族自治州11是否需要将结果输出到文件中才能进行?其实不一定如此。使用管道方法|将上一条命令的输出作为下一条命令的输入,使用<(command)方法将命令的输出作为文件输入。#需要排序?shell-train>join-11-22city.code4<(head-n10topcity.code|sort-k2)1201天津市区1971301河北省石家庄市1141302河北省唐山市1561324河北省保定区1031501内蒙古呼和浩特市882101辽宁省沉阳市1092201吉林省长春市1132301黑龙江省哈尔滨市1234201湖北省武汉市1186101陕西省西安市100比如paste用于将两个文件合并在一起在列中:?shell-train>catpaste.f1hello,iamworld,youare?shell-train>catpaste.f2tanglei,wechatis:tangleithu?,hahaha?shell-train>pastepaste.f1paste.f2hello,iamtanglei,wechatis:tangleithuworld,youare?,哈哈哈上面用paste把两个文件合并在一起,其实就是借助于<(cmd),不需要借助外部文件就可以完成。方法如下:?shell-train>paste<(echo"hello,iam\nworld,youare")<(echo"tanglei,wechatis:tangleithu\n?,haha??ha")hello,iamtanglei,wechatis:tangleithuworld,youare?,哈哈哈本文转载自微信公众号“程序猿石”,可通过以下二维码关注。转载本文请联系程序员公众号。
