1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        沒想到 Shell 命令竟然還能這么玩?

        共 5759字,需瀏覽 12分鐘

         ·

        2020-08-19 18:07


        前奏

        本文是一個命令行工具的綜合應(yīng)用,將用一個具體的例子來闡述如何用 Shell 來進(jìn)行高效地?cái)?shù)據(jù)統(tǒng)計(jì)和分析。最近北京又開始了新一批積分落戶的填報(bào)工作,恰好這篇文章用 shell 來對首批北京積分落戶同學(xué)進(jìn)行 "大數(shù)據(jù)"分析。
        現(xiàn)如今到處都是各種"大數(shù)據(jù)",本文分析對象也就是首批積分落戶的6000多條數(shù)據(jù)而已,顯然不能算什么大數(shù)據(jù)。
        印象中,我記得當(dāng)初該官網(wǎng)的這6000多條數(shù)據(jù)也是一次性就能wget下來的(后端估計(jì)沒做限制,可能稍微調(diào)整下接口的分頁參數(shù)之類不需要嚴(yán)格按照各種分頁多次下載)。

        問題描述

        輸入是 json數(shù)據(jù),格式化之后的 json 數(shù)據(jù)主題結(jié)構(gòu)如下所示,rows為數(shù)組,數(shù)組中元素所代表的 object 即描述了獲得北京戶口的同學(xué)的各種屬性:例如分?jǐn)?shù)、排名、身份證號(后四位打碼了)、公司等等信息。為了方便大家練習(xí)對數(shù)據(jù)進(jìn)行試驗(yàn),我將文中的數(shù)據(jù)附在這里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":?"北京利德華福電氣技術(shù)有限公司"
        },
        拿到這個文件,比如希望你用最快的方法獲得以下信息,你將會怎么做?
        • 獲取取得戶口名額最多的top10公司
        • 獲取取得戶口名額的人中姓氏最多的
        • 獲取戶口名字中叫啥名最流行
        • 獲取年齡分布
        • 獲取取得戶口的同學(xué)戶籍地top10
        • 生肖/星座/生日...
        當(dāng)然,方法有很多,比如熟悉各種編程語言的,例如?python, php, java?等等寫個簡單的腳本程序,也能比較快獲取答案?;蛘甙严鄳?yīng)的數(shù)據(jù)提取出來,放到 excel 中也可以。
        如果你對 Shell 很熟悉,那真的是分分鐘,應(yīng)該是秒秒就能獲取答案。就算用 Shell 來實(shí)現(xiàn),不同的人可能也有不同的寫法,后面我就列舉其中的一種來解決這些問題。
        本文不對 Shell 具體每個命令做過多的解釋,不熟悉的同學(xué)可以直接?man $cmd?或者?$cmd --help?等等查看。

        問題解答

        獲取取得戶口名額最多的top10公司

        看看想通過積分落戶,最好是進(jìn)哪些公司,哈哈。
        "unit": "北京利德華福電氣技術(shù)有限公司"

        先通過?grep?得到包含公司名字的一行,然后通過 ":" 分割?cut?取第2列得到公司名字,對結(jié)果進(jìn)行sort排序進(jìn)行去重uniq統(tǒng)計(jì)得到重復(fù)次數(shù),次時結(jié)果為重復(fù)次數(shù) 公司名,再對第一列-k 1重復(fù)數(shù)字進(jìn)行按照數(shù)字排序逆序-nr?即?sort -nr -k 1,最后取結(jié)果的前10行?head -n 10。
        ???積分落戶??>?grep?'unit'?jifenluohu.json|?cut?-f2?-d:?|?sort?|?uniq?-c?|?sort?-nr?-k?1?|?head?-n?10
        ?137??"北京華為數(shù)字技術(shù)有限公司"
        ??73??"中央電視臺"
        ??57??"北京首鋼建設(shè)集團(tuán)有限公司"
        ??55??"百度在線網(wǎng)絡(luò)技術(shù)(北京)有限公司"
        ??48??"聯(lián)想(北京)有限公司"
        ??40??"北京外企人力資源服務(wù)有限公司"
        ??40??"中國民生銀行股份有限公司"
        ??39??"國際商業(yè)機(jī)器(中國)投資有限公司"
        ??29??"中國國際技術(shù)智力合作有限公司"
        ??27??"華為技術(shù)有限公司北京研究所"

        獲取取得戶口名額的人中姓氏最多的

        看看想通過積分落戶,最好是姓啥,哈哈。
        "name": "楊效豐",
        套路跟之前差不多的,我這邊就不特別指出了。
        下面shell實(shí)際上是取到這行后,將真正表示名字之前的所有字符都刪除,就只剩下名字開頭了,取行首第一個字符cut -c 1即得到姓,再按照之前的套路就能拿到了。
        其實(shí)用什么sed替換冗余的字符都是多余的,因?yàn)閖son的格式都是良好的,可以直接通過?cut -c ??取姓這個字符即可。
        也不用挨個去數(shù)到底是第幾個字符,直接 copy出來,然后?echo -n $paste | wc -c?就能數(shù)到第幾個字符了。
        看結(jié)果還是姓 "張, 王" 之類的最有戲。?
        #?或者?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?10
        ?541?張
        ?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?10
        ??51?偉",
        ??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?10
        ??19?海濤
        ??19?曉東
        ??12?志強(qiáng)
        ??11?海燕
        ??11?永強(qiáng)
        ??11?建華
        ??10?雪梅
        ???9?海龍
        ???9?麗娜
        ???8?洪濤
        作為碼農(nóng),必須得養(yǎng)成對自己得到結(jié)果進(jìn)行自測的習(xí)慣,所以如果對自己的結(jié)果不夠自信,可以正向去計(jì)算一下最終的結(jié)果。
        例如可以簡單grep一下進(jìn)行驗(yàn)證,叫 "海濤" 的是不是19個。
        ???積分落戶??>?grep?'海濤'?jifenluohu.json?|?wc?-l
        ??????19??

        獲取年齡分布

        思路是截取身份證中號碼中代表出生年的4位數(shù),然后拿當(dāng)前年份2019減出生年得到年齡,后面的套路又一樣了。
        bc?一個簡單的計(jì)算器程序,了解下?
        ???shell-train??>?echo?"3+2-5/5"?|?bc
        4
        ???shell-train??>?echo?"3.141592*5-4"?|?bc
        11.707960
        #思路1:?`cut?-c?9-12`?獲取出生年,?拼接表達(dá)式?`2019-出生年`?得到年齡.
        ???積分落戶??>?grep?'"idCard":'?jifenluohu.json|?cut?-f2?-d:?|?cut?-c?9-12?|?xargs?-n1?echo?2019?-|bc?|?sort?|?uniq?-c
        ???3?34
        ??13?35
        ??39?36
        ?109?37
        ?162?38
        ?302?39
        ?507?40
        ?773?41
        ?799?42
        ?813?43
        ?757?44
        ?586?45
        ?507?46
        ?378?47
        ?238?48
        ???4?49
        ???9?50
        ???1?51
        ???4?52
        ???3?53
        ???2?54
        ???5?55
        ???1?56
        ???1?58
        ???1?59
        ???1?60
        ???1?61
        awk?是個好東西, 多練練.
        #?拿到出生年后,?直接通過?awk?計(jì)算結(jié)果輸出
        ???積分落戶??>?grep?'"idCard":'?jifenluohu.json|?cut?-f2?-d:?|?cut?-c?9-12?|awk?'{print?2019-$1}'?|?sort?|?uniq?-c
        ???3?34
        ??13?35
        ??39?36
        ?109?37
        ?162?38
        ?302?39
        ?507?40
        ?773?41
        ?799?42
        ?813?43
        ?757?44
        ?586?45
        ?507?46
        ?378?47
        ?238?48
        ???4?49
        ???9?50
        ???1?51
        ???4?52
        ???3?53
        ???2?54
        ???5?55
        ???1?56
        ???1?58
        ???1?59
        ???1?60
        ???1?61???

        獲取取得戶口的同學(xué)戶籍地top10

        有時候,我們在寫Shell的時候,為了debug方便,可能會將一些中間結(jié)果緩存到文件中,后續(xù)以該文件為基礎(chǔ)進(jìn)行后續(xù)的計(jì)算。
        比如先拿到top10的身份證中代表的戶籍地的四位編碼,這里需要借助另外的一個表示身份證戶籍地的編碼來進(jìn)行對應(yīng)。
        借此機(jī)會解釋下?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,北京市市轄區(qū)
        110101,北京市東城區(qū)
        110102,北京市西城區(qū)
        110103,北京市崇文區(qū)
        110104,北京市宣武區(qū)
        110105,北京市朝陽區(qū)
        #?grep?-E?'^[0-9]{4},'?city.csv?|?sed?'s|,|?|g'?>?city.code4
        ??shell-train??>?head?-n?2?city.code4
        1101?北京市市轄區(qū)
        1102?北京市市轄縣
        ??shell-train??>?head?-n?2?topcity.code
        ?197?1201
        ?156?1302
        ??shell-train??>?join
        usage:?join?[-a?fileno?|?-v?fileno?]?[-e?string]?[-1?field]?[-2?field]
        ????????????[-o?list]?[-t?char]?file1?file2
        其實(shí),join?就類似sql中的?...inner join ...on ...,?-t?分隔符,默認(rèn)為空格或tab。
        #?未排序,?所以沒有將所有的導(dǎo)出(join需要排序)
        ??shell-train??>?join?-1?1?-2?2?city.code4?topcity.code
        1201?天津市市轄區(qū)?197
        1302?河北省唐山市?156
        2301?黑龍江哈爾濱市?123
        4201?湖北省武漢市?118
        6101?陜西省西安市?100
        6201?甘肅省蘭州市?59
        6501?新疆烏魯木齊市?29
        6523?新疆昌吉回族自治州?11
        一定需要將結(jié)果輸出到文件,然后再進(jìn)行嗎?
        其實(shí)也不一定。用管道的方式?|?可以將上一個命令的輸出結(jié)果作為下一個命令的輸入,可以通過?<(command)?的方式,將command?的輸出作為一個文件輸入。
        #?需要排序
        ??shell-train??>?join?-1?1?-2?2?city.code4?<(head?-n?10?topcity.code?|?sort?-k?2)
        1201?天津市市轄區(qū)?197
        1301?河北省石家莊市?114
        1302?河北省唐山市?156
        1324?河北省保定地區(qū)?103
        1501?內(nèi)蒙古呼和浩特市?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將兩個文件合并在一起了,實(shí)際上通過?<(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

        其他的任務(wù)交給你了

        這里就不重復(fù)多講了,剩下的問題,要不你動手試試,比如看看生日最多的?
        再試試獲取 生肖/星座 最多的top10。
        有任何疑問,歡迎留言交流參與交流討論。

        -?掃下面二維碼,獲取23套完整的編程視頻資料?-


        2T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,人工智能,考研,軟考,英語,等等。在公眾號內(nèi)回復(fù)「資源」,即可免費(fèi)獲取!回復(fù)「社群」,可以邀請你加入讀者群!


        明天見(??ω??)??
        瀏覽 38
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            国产日批视频 | 国产婷婷久久 | 亚洲日韩欧洲无码A∨夜夜爽 | 成人色情网站在线观看 | 国产a级免费观看 | 成人片av一区青青草 | 国产精品久久丝袜人妻 | 好吊色综合高清 | 俺来操| 男人的天堂黄色视频 |