<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 5758字,需瀏覽 12分鐘

           ·

          2020-11-03 09:21



          點擊「閱讀原文」查看良許原創(chuàng)精品視頻。


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

          問題描述

          輸入是 json數(shù)據(jù),格式化之后的 json 數(shù)據(jù)主題結構如下所示,rows為數(shù)組,數(shù)組中元素所代表的 object 即描述了獲得北京戶口的同學的各種屬性:例如分數(shù)、排名、身份證號(后四位打碼了)、公司等等信息。

          "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ù)據(jù)進行試驗,我將文中的數(shù)據(jù)附在這里:https://www.tanglei.name/resources/use-shell-to-analysis-the-first-people-of-getting-residence-of-beijing-by-score/jifenluohu.json.gz

          拿到這個文件,比如希望你用最快的方法獲得以下信息,你將會怎么做?

          • 獲取取得戶口名額最多的top10公司
          • 獲取取得戶口名額的人中姓氏最多的
          • 獲取戶口名字中叫啥名最流行
          • 獲取年齡分布
          • 獲取取得戶口的同學戶籍地top10
          • 生肖/星座/生日...

          當然,方法有很多,比如熟悉各種編程語言的,例如?python, php, java?等等寫個簡單的腳本程序,也能比較快獲取答案。或者把相應的數(shù)據(jù)提取出來,放到 excel 中也可以。

          如果你對 Shell 很熟悉,那真的是分分鐘,應該是秒秒就能獲取答案。就算用 Shell 來實現(xiàn),不同的人可能也有不同的寫法,后面我就列舉其中的一種來解決這些問題。

          本文不對 Shell 具體每個命令做過多的解釋,不熟悉的同學可以直接?man $cmd?或者?$cmd --help?等等查看。

          問題解答

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

          看看想通過積分落戶,最好是進哪些公司,哈哈。

          "unit": "北京利德華福電氣技術有限公司"

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

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

          看看想通過積分落戶,最好是姓啥,哈哈。

          "name": "楊效豐",

          套路跟之前差不多的,我這邊就不特別指出了。

          下面shell實際上是取到這行后,將真正表示名字之前的所有字符都刪除,就只剩下名字開頭了,取行首第一個字符cut -c 1即得到姓,再按照之前的套路就能拿到了。

          其實用什么sed替換冗余的字符都是多余的,因為json的格式都是良好的,可以直接通過?cut -c ??取姓這個字符即可。

          也不用挨個去數(shù)到底是第幾個字符,直接 copy出來,然后?echo -n $paste | wc -c?就能數(shù)到第幾個字符了。

          看結果還是姓 "張, 王" 之類的最有戲。?

          #?或者?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?志強
          ??11?海燕
          ??11?永強
          ??11?建華
          ??10?雪梅
          ???9?海龍
          ???9?麗娜
          ???8?洪濤

          作為碼農(nóng),必須得養(yǎng)成對自己得到結果進行自測的習慣,所以如果對自己的結果不夠自信,可以正向去計算一下最終的結果。

          例如可以簡單grep一下進行驗證,叫 "海濤" 的是不是19個。

          ???積分落戶??>?grep?'海濤'?jifenluohu.json?|?wc?-l
          ??????19??

          獲取年齡分布

          思路是截取身份證號碼中代表出生年的4位數(shù),然后拿當前年份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?-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?計算結果輸出
          ???積分落戶??>?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???

          獲取取得戶口的同學戶籍地top10

          有時候,我們在寫Shell的時候,為了debug方便,可能會將一些中間結果緩存到文件中,后續(xù)以該文件為基礎進行后續(xù)的計算。

          比如先拿到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,北京市市轄區(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

          其實,join?就類似sql中的?...inner join ...on ...,?-t?分隔符,默認為空格或tab

          #?未排序,?所以沒有將所有的導出(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

          一定需要將結果輸出到文件,然后再進行嗎?

          其實也不一定。用管道的方式?|?可以將上一個命令的輸出結果作為下一個命令的輸入,可以通過?<(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將兩個文件合并在一起了,實際上通過?<(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。

          套路是一樣的,這里就不重復多講了。

          彩蛋

          最后,推薦一個shell處理json的工具——jq工具,可以減少很多過濾命令,讓操作更加簡潔、高效。



          良許個人微信


          添加良許個人微信即送3套程序員必讀資料


          → 精選技術資料共享

          → 高手如云交流社群





          本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲取!

          推薦閱讀:

          優(yōu)麒麟20.10終極預告,界面比較養(yǎng)眼

          世界上最難的5種編程語言

          吳恩達給 74 歲老父親發(fā)證了!8 年完成 146 門課程!


          5T技術資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機,樹莓派,等等。在公眾號內(nèi)回復「1024」,即可免費獲取!!


          瀏覽 68
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷日逼 | 爱搞搞91搞搞 | 久草加勒比 | 少妇人妻在线播放 | 一级特黄色片 |