亚洲精品亚洲人成在线观看麻豆,在线欧美视频一区,亚洲国产精品一区二区动图,色综合久久丁香婷婷

              當前位置:首頁 > IT技術 > 其他 > 正文

              jq命令用法總結
              2022-05-29 22:41:52

              原創(chuàng):扣釘日記(微信公眾號ID:codelogs),歡迎分享,轉載請保留出處。

              簡介

              如果說要給Linux文本三劍客(grep、sed、awk)添加一員的話,我覺得應該是jq命令,因為jq命令是用來處理json數(shù)據(jù)的工具,而現(xiàn)如今json幾乎無所不在!

              網(wǎng)上的jq命令分享文章也不少,但大多介紹得非常淺,jq的強大之處完全沒有介紹出來,所以就有了這篇文章,安利一下jq這個命令。

              基本用法

              格式化

              # jq默認的格式化輸出
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq .
              {
                "id": 1,
                "name": "zhangsan",
                "score": [
                  75,
                  85,
                  90
                ]
              }
              
              # -c選項則是壓縮到1行輸出
              $ jq -c . <<eof
              {
                "id": 1,
                "name": "zhangsan",
                "score": [
                  75,
                  85,
                  90
                ]
              }
              eof
              {"id":1,"name":"zhangsan","score":[75,85,90]}
              

              屬性提取

              # 獲取id字段
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq '.id'
              1
              # 獲取name字段
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq '.name'
              "zhangsan"
              
              # 獲取name字段,-r 解開字符串引號
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq -r '.name'
              zhangsan
              
              # 多層屬性值獲取
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr.height'
              1.78
              
              # 獲取數(shù)組中的值
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq -r '.score[0]'
              75
              
              $ echo -n '[75, 85, 90]'|jq -r '.[0]'
              75
              
              # 數(shù)組截取
              $ echo -n '[75, 85, 90]'|jq -r '.[1:3]'
              [
                85,
                90
              ]
              
              # []展開數(shù)組
              $ echo -n '[75, 85, 90]'|jq '.[]'
              75
              85
              90
              
              # ..展開所有結構
              $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq -c '..'
              {"id":1,"name":"zhangsan","score":[75,85,90]}
              1
              "zhangsan"
              [75,85,90]
              75
              85
              90
              
              # 從非對象類型中提取字段,會報錯
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.name.alias'
              jq: error (at <stdin>:0): Cannot index string with string "alias"
              
              # 使用?號可以避免這種報錯
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.name.alias?'
              
              # //符號用于,當前面的表達式取不到值時,執(zhí)行后面的表達式
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.alias//.name'
              "zhangsan"
              

              管道、逗號與括號

              # 管道可以將值從前一個命令傳送到后一個命令
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr|.height'
              1.78
              
              # jq中做一些基礎運算也是可以的
              $ echo -n '{"id":1, "name":"zhangsan", "attr":{"height":1.78,"weight":"60kg"}}'|jq '.attr|.height*100|tostring + "cm"'
              "178cm"
              
              # 逗號使得可以執(zhí)行多個jq表達式,使得一個輸入可計算出多個輸出結果
              $ echo 1 | jq '., ., .'
              1
              1
              1
              
              # 括號用于提升表達式的優(yōu)先級,如下:逗號優(yōu)先級低于算術運算
              $ $ echo '1'|jq '.+1, .*2'
              2
              2
              
              $ echo '1'|jq '(.+1, .)*2'
              4
              2
              
              # 管道優(yōu)先級低于逗號
              $ echo '1'|jq '., .|tostring'
              "1"
              "1"
              
              $ echo '1'|jq '., (.|tostring)'
              1
              "1"
              

              理解jq執(zhí)行過程

              表面上jq是用來處理json數(shù)據(jù)的,但實際上jq能處理的是任何json基礎元素所形成的流,如integer、string、bool、null、object、array等,jq執(zhí)行過程大致如下:

              1. jq從流中獲取一個json元素
              2. jq執(zhí)行表達式,表達式生成新的json元素
              3. jq將新的json元素打印輸出

              可以看看這些示例,如下:

              # 這里jq實際上將1 2 3 4當作4個integer元素,每找到一個元素就執(zhí)行+1操作
              # jq實際上是流式處理的,1 2 3 4可以看成流中的4個元素
              $ echo '1 2 3 4'|jq '. + 1'
              2
              3
              4
              5
              
              # 流中的元素不需要是同種類型,只要是完整的json元素即可
              $ jq '"<" + tostring + ">"' <<eof
              1
              "zhangsan"
              true
              {"id":1}
              [75, 80, 85]
              eof
              
              "<1>"
              "<zhangsan>"
              "<true>"
              "<{"id":1}>"
              "<[75,80,85]>"
              
              # -R選項可用于將讀取到的json元素,都當作字符串對待
              $ seq 4|jq -R '.'
              "1"
              "2"
              "3"
              "4"
              
              # -s選項將從流中讀取到的所有json元素,變成一個json數(shù)組元素  
              # 這里理解為jq從流中只取到了1個json元素,這個json元素的類型是數(shù)組
              $ seq 4|jq -s .
              [
                1,
                2,
                3,
                4
              ]
              

              基礎運算

              jq支持 + - * / % 運算,對于+號,如果是字符串類型,則是做字符串拼接,如下:

              # 做加減乘除運算
              $ echo 1|jq '.+1, .-1, .*2, ./2, .%2'
              2
              0
              2
              0.5
              1
              
              # 賦值運算
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq '.id=2' -c
              {"id":2,"name":"zhangsan","age":"17","score":"75"}
              

              數(shù)據(jù)構造

              jq可以很方便的將其它數(shù)據(jù),轉化為json對象或數(shù)組,如下:

              # 使用[]構造數(shù)組元素,-n告訴jq沒有輸入數(shù)據(jù),直接執(zhí)行表達式并生成輸出數(shù)據(jù)
              $ jq -n '[1,2,3,4]' -c
              [1,2,3,4]
              
              $ cat data.txt
              id  name      age  score
              1   zhangsan  17   75
              2   lisi      16   80
              3   wangwu    18   85
              4   zhaoliu   18   90
              
              # 每行分割成數(shù)組,[]構造新的數(shù)組輸出
              $ tail -n+2 data.txt|jq -R '[splits("\s+")]' -c
              ["1","zhangsan","17","75"]
              ["2","lisi","16","80"]
              ["3","wangwu","18","85"]
              ["4","zhaoliu","18","90"]
              
              $ jq -n '{id:1, name:"zhangsan"}' -c
              {"id":1,"name":"zhangsan"}
              
              # 每行轉換為對象,{}構造新的對象格式輸出
              $ tail -n+2 data.txt|jq -R '[splits("\s+")] | {id:.[0]|tonumber, name:.[1], age:.[2], score:.[3]}' -c
              {"id":1,"name":"zhangsan","age":"17","score":"75"}
              {"id":2,"name":"lisi","age":"16","score":"80"}
              {"id":3,"name":"wangwu","age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","age":"18","score":"90"}
              
              # ()字符串占位變量替換
              $ cat data.json
              {"id":1,"name":"zhangsan","age":"17","score":"75"}
              {"id":2,"name":"lisi","age":"16","score":"80"}
              {"id":3,"name":"wangwu","age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","age":"18","score":"90"}
              
              $ cat data.json |jq '"id:(.id),name:(.name),age:(.age),score:(.score)"' -r
              id:1,name:zhangsan,age:17,score:75
              id:2,name:lisi,age:16,score:80
              id:3,name:wangwu,age:18,score:85
              id:4,name:zhaoliu,age:18,score:90
              

              基礎函數(shù)

              # has函數(shù),檢測對象是否包含key
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'has("id")'
              true
              
              # del函數(shù),刪除某個屬性
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'del(.id)' -c
              {"name":"zhangsan","age":"17","score":"75"}
              
              # map函數(shù),對數(shù)組中每個元素執(zhí)行表達式計算,計算結果組織成新數(shù)組
              $ seq 4|jq -s 'map(. * 2)' -c
              [2,4,6,8]
              
              # 上面map函數(shù)寫法,其實等價于這個寫法
              $ seq 4|jq -s '[.[]|.*2]' -c
              [2,4,6,8]
              
              # keys函數(shù),列出對象屬性
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'keys' -c
              ["age","id","name","score"]
              
              # to_entries函數(shù),列出對象鍵值對
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","score":"75"}'|jq 'to_entries' -c
              [{"key":"id","value":1},{"key":"name","value":"zhangsan"},{"key":"age","value":"17"},{"key":"score","value":"75"}]
              
              # length函數(shù),計算數(shù)組或字符串長度
              $ jq -n '[1,2,3,4]|length'
              4
              
              # add函數(shù),計算數(shù)組中數(shù)值之和
              $ seq 4|jq -s 'add'
              10
              
              # tostring與tonumber,類型轉換
              $ seq 4|jq 'tostring|tonumber'
              1
              2
              3
              4
              
              # type函數(shù),獲取元素類型
              $ jq 'type' <<eof
              1
              "zhangsan"
              true
              null
              {"id":1}
              [75, 80, 85]
              eof
              
              "number"
              "string"
              "boolean"
              "null"
              "object"
              "array"
              

              過濾、排序、分組函數(shù)

              $ cat data.json
              {"id":1,"name":"zhangsan","sex": 0, "age":"17","score":"75"}
              {"id":2,"name":"lisi","sex": 1, "age":"16","score":"80"}
              {"id":3,"name":"wangwu","sex": 0, "age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","sex": 0, "age":"18","score":"90"}
              
              # select函數(shù)用于過濾,類似SQL中的where
              $ cat data.json |jq 'select( (.id>1) and (.age|IN("16","17","18")) and (.name != "lisi") or (has("attr")|not) and (.score|tonumber >= 90) )' -c
              {"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}
              
              # 有一些簡化的過濾函數(shù),如arrays, objects, iterables, booleans, numbers, normals, finites, strings, nulls, values, scalars
              # 它們根據(jù)類型過濾,如objects過濾出對象,values過濾出非null值等
              $ jq -c 'objects' <<eof
              1
              "zhangsan"
              true
              null
              {"id":1}
              [75, 80, 85]
              eof
              
              {"id":1}
              
              $ jq -c 'values' <<eof
              1
              "zhangsan"
              true
              null
              {"id":1}
              [75, 80, 85]
              eof
              
              1
              "zhangsan"
              true
              {"id":1}
              [75,80,85]
              
              # 選擇出id與name字段,類似SQL中的select id,name
              $ cat data.json|jq -s 'map({id,name})[]' -c
              {"id":1,"name":"zhangsan"}
              {"id":2,"name":"lisi"}
              {"id":3,"name":"wangwu"}
              {"id":4,"name":"zhaoliu"}
              
              # 提取前2行,類似SQL中的limit 2
              $ cat data.json|jq -s 'limit(2; map({id,name})[])' -c
              {"id":1,"name":"zhangsan"}
              {"id":2,"name":"lisi"}
              
              # 按照age、id排序,類似SQL中的order by age,id
              $ cat data.json|jq -s 'sort_by((.age|tonumber), .id)[]' -c
              {"id":2,"name":"lisi","sex":1,"age":"16","score":"80"}
              {"id":1,"name":"zhangsan","sex":0,"age":"17","score":"75"}
              {"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}
              
              
              # 根據(jù)sex與age分組,并每組聚合計算count(*)、avg(score)、max(id)
              $ cat data.json |jq -s 'group_by(.sex, .age)[]' -c
              [{"id":1,"name":"zhangsan","sex":0,"age":"17","score":"75"}]
              [{"id":3,"name":"wangwu","sex":0,"age":"18","score":"85"},{"id":4,"name":"zhaoliu","sex":0,"age":"18","score":"90"}]
              [{"id":2,"name":"lisi","sex":1,"age":"16","score":"80"}]
              
              $ cat data.json |jq -s 'group_by(.sex, .age)[]|{sex:.[0].sex, age:.[0].age, count:length, avg_score:map(.score|tonumber)|(add/length), scores:map(.score)|join(","), max_id:map(.id)|max }' -c                 
              {"sex":0,"age":"17","count":1,"avg_score":75,"scores":"75","max_id":1}
              {"sex":0,"age":"18","count":2,"avg_score":87.5,"scores":"85,90","max_id":4}
              {"sex":1,"age":"16","count":1,"avg_score":80,"scores":"80","max_id":2}
              
              

              字符串操作函數(shù)

              # contains函數(shù),判斷是否包含,實際也可用于判斷數(shù)組是否包含某個元素
              $ echo hello | jq -R 'contains("he")'
              true
              
              # 判斷是否以he開頭
              $ echo hello | jq -R 'startswith("he")'
              true
              
              # 判斷是否以llo結尾
              $ echo hello | jq -R 'endswith("llo")'
              true
              
              # 去掉起始空格
              $ echo ' hello '|jq -R 'ltrimstr(" ")|rtrimstr(" ")'
              "hello"
              
              # 大小寫轉換
              $ echo hello|jq -R 'ascii_upcase'
              "HELLO"
              
              $ echo HELLO|jq -R 'ascii_downcase'
              "hello"
              
              # 字符串數(shù)組,通過逗號拼接成一個字符串
              $ seq 4|jq -s 'map(tostring)|join(",")'
              "1,2,3,4"
              
              # json字符串轉換為json對象
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","attr":"{"weight":56,"height":178}"}'|jq '.attr = (.attr|fromjson)' -c
              {"id":1,"name":"zhangsan","age":"17","attr":{"weight":56,"height":178}}
              
              # json對象轉換為json字符串
              $ echo -n '{"id":1,"name":"zhangsan","age":"17","attr":{"weight":56,"height":178}}'|jq '.attr = (.attr|tojson)'
              {
                "id": 1,
                "name": "zhangsan",
                "age": "17",
                "attr": "{"weight":56,"height":178}"
              }
              
              $ cat data.txt
              id:1,name:zhangsan,age:17,score:75
              id:2,name:lisi,age:16,score:80
              id:3,name:wangwu,age:18,score:85
              id:4,name:zhaoliu,age:18,score:90
              
              # 正則表達式過濾,jq使用的是PCRE
              $ cat data.txt|jq -R 'select(test("id:\d+,name:\w+,age:\d+,score:8\d+"))' -r
              id:2,name:lisi,age:16,score:80
              id:3,name:wangwu,age:18,score:85
              
              # 正則拆分字符串
              $ cat data.txt|jq -R '[splits(",")]' -cr
              ["id:1","name:zhangsan","age:17","score:75"]
              ["id:2","name:lisi","age:16","score:80"]
              ["id:3","name:wangwu","age:18","score:85"]
              ["id:4","name:zhaoliu","age:18","score:90"]
              
              # 正則替換字符串
              $ cat data.txt |jq -R 'gsub("name"; "nick")' -r
              id:1,nick:zhangsan,age:17,score:75
              id:2,nick:lisi,age:16,score:80
              id:3,nick:wangwu,age:18,score:85
              id:4,nick:zhaoliu,age:18,score:90
              
              # 正則表達式捕獲數(shù)據(jù)
              $ cat data.txt|jq -R 'match("id:(?<id>\d+),name:(?<name>\w+),age:\d+,score:8\d+")' -cr
              {"offset":0,"length":30,"string":"id:2,name:lisi,age:16,score:80","captures":[{"offset":3,"length":1,"string":"2","name":"id"},{"offset":10,"length":4,"string":"lisi","name":"name"}]}
              {"offset":0,"length":32,"string":"id:3,name:wangwu,age:18,score:85","captures":[{"offset":3,"length":1,"string":"3","name":"id"},{"offset":10,"length":6,"string":"wangwu","name":"name"}]}
              
              # capture命名捕獲,生成key是捕獲組名稱,value是捕獲值的對象
              $ cat data.txt|jq -R 'capture("id:(?<id>\d+),name:(?<name>\w+),age:\d+,score:8\d+")' -rc
              {"id":"2","name":"lisi"}
              {"id":"3","name":"wangwu"}
              
              # 正則掃描輸入字符串
              $ cat data.txt|jq -R '[scan("\w+:\w+")]' -rc
              ["id:1","name:zhangsan","age:17","score:75"]
              ["id:2","name:lisi","age:16","score:80"]
              ["id:3","name:wangwu","age:18","score:85"]
              ["id:4","name:zhaoliu","age:18","score:90"]
              

              日期函數(shù)

              # 當前時間綴
              $ jq -n 'now'
              1653820640.939947
              
              # 將時間綴轉換為0時區(qū)的分解時間(broken down time),形式為 年 月 日 時 分 秒 dayOfWeek dayOfYear
              $ jq -n 'now|gmtime' -c
              [2022,4,29,10,45,5.466768980026245,0,148]
              
              # 將時間綴轉換為本地時區(qū)的分解時間(broken down time)
              $ jq -n 'now|localtime' -c
              [2022,4,29,18,46,5.386353015899658,0,148]
              
              # 分解時間轉換為時間串
              $ jq -n 'now|localtime|strftime("%Y-%m-%dT%H:%M:%S")' -c
              "2022-05-29T18:50:33"
              
              # 與上面等效
              $ jq -n 'now|strflocaltime("%Y-%m-%dT%H:%M:%SZ")'
              "2022-05-29T19:00:40Z"
              
              # 時間串解析為分解時間
              $ date +%FT%T|jq -R 'strptime("%Y-%m-%dT%H:%M:%S")' -c
              [2022,4,29,18,51,27,0,148]
              
              # 分解時間轉換為時間綴
              $ date +%FT%T|jq -R 'strptime("%Y-%m-%dT%H:%M:%S")|mktime'
              1653850310
              

              高級用法

              實際上jq是一門腳本語言,它也支持變量、分支結構、循環(huán)結構與自定義函數(shù),如下:

              $ cat data.json
              {"id":1,"name":"zhangsan","sex": 0, "age":"17","score":"75"}
              {"id":2,"name":"lisi","sex": 1, "age":"16","score":"80"}
              {"id":3,"name":"wangwu","sex": 0, "age":"18","score":"85"}
              {"id":4,"name":"zhaoliu","sex": 0, "age":"18","score":"90"}
              
              # 單變量定義
              $ cat data.json| jq '.id as $id|$id'
              1
              2
              3
              4
              
              # 對象展開式變量定義
              $ cat data.json |jq '. as {id:$id,name:$name}|"id:($id),name:($name)"'
              "id:1,name:zhangsan"
              "id:2,name:lisi"
              "id:3,name:wangwu"
              "id:4,name:zhaoliu"
              
              $ cat data.json
              ["1","zhangsan","17","75"]
              ["2","lisi","16","80"]
              ["3","wangwu","18","85"]
              ["4","zhaoliu","18","90"]
              
              # 數(shù)組展開式變量定義
              $ cat data.json|jq '. as [$id,$name]|"id:($id),name:($name)"'
              "id:1,name:zhangsan"
              "id:2,name:lisi"
              "id:3,name:wangwu"
              "id:4,name:zhaoliu"
              
              # 分支結構
              $ cat data.json|jq '. as [$id,$name]|if ($id>"1") then "id:($id),name:($name)" else empty end'
              "id:2,name:lisi"
              "id:3,name:wangwu"
              "id:4,name:zhaoliu"
              
              # 循環(huán)結構,第一個表達式條件滿足時,執(zhí)行只每二個表達式
              # 循環(huán)結構除了while,還有until、recurse等
              $ echo 1|jq 'while(.<100; .*2)'
              1
              2
              4
              8
              16
              32
              64
              
              # 自定義計算3次方的函數(shù)
              $ echo 2|jq 'def cube: .*.*. ; cube'
              8
              

              由于這些高級特性并不常用,這里僅給出了一些簡單示例,詳細使用可以man jq查看。

              輔助shell編程

              熟悉shell腳本編程的同學都知道,shell本身是沒有提供Map、List這種數(shù)據(jù)結構的,這導致使用shell實現(xiàn)某些功能時,變得很棘手。

              但jq本身是處理json的,而json中的對象就可等同于Map,json中的數(shù)組就可等同于List,如下:

              list='[]';
              #List添加元素
              list=$(echo "$list"|jq '. + [ $val ]' --arg val java);
              list=$(echo "$list"|jq '. + [ $val ]' --arg val shell);
              #獲取List大小
              echo "$list"|jq '.|length'
              #獲取List第1個元素
              echo "$list"|jq '.[0]' -r
              # List是否包含java字符串
              echo "$list"|jq 'any(.=="java")'
              #刪除List第1個元素
              list=$(echo "$list"|jq 'del(.[0])');
              # List合并
              list=$(echo "$list"|jq '. + $val' --argjson val '["shell","python"]');
              # List截取
              echo "$list"|jq '.[1:3]'
              # List遍歷
              for o in $(echo "$list" | jq -r '.[]');do 
                  echo "$o"; 
              done
              
              map='{}';
              #Map添加元素
              map=$(echo "$map"|jq '.id=$val' --argjson val 1)
              map=$(echo "$map"|jq '.courses=$val' --argjson val "$list")
              #獲取Map大小
              echo "$map"|jq '.|length'
              #獲取Map指定key的值
              echo "$map"|jq '.id' -r
              #判斷Map指定key是否存在
              echo "$map" | jq 'has("id")'
              #刪除Map指定key
              map=$(echo "$map"|jq 'del(.id)')
              # Map合并
              map=$(echo "$map"|jq '. + $val' --argjson val '{"code":"ID001","name":"hello"}')
              # Map的KeySet遍歷
              for key in $(echo "$map" | jq -r 'keys[]'); do 
                  value=$(jq '.[$a]' --arg a "$key" -r <<<"$map"); 
                  printf "%s:%s
              " "$key" "$value"; 
              done
              # Map的entrySet遍歷
              while read -r line; do 
                  key=$(jq '.key' -r <<<"$line"); 
                  value=$(jq '.value' -r <<<"$line"); 
                  printf "%s:%s
              " "$key" "$value"; 
              done <<<$(echo "$map" | jq 'to_entries[]' -c)
              

              總結

              可以發(fā)現(xiàn),jq已經(jīng)實現(xiàn)了json數(shù)據(jù)處理與分析的方方面面,我個人最近在工作中,也多次使用jq來分析調(diào)用日志等,用起來確實非常方便。

              如果你現(xiàn)在還沒完全學會jq的用法,沒關系,建議先收藏起來,后面一定會用得到的!

              往期內(nèi)容

              密碼學入門
              q命令-用SQL分析文本文件
              神秘的backlog參數(shù)與TCP連接隊列
              mysql的timestamp會存在時區(qū)問題?
              真正理解可重復讀事務隔離級別
              字符編碼解惑

              本文摘自 :https://www.cnblogs.com/

              開通會員,享受整站包年服務立即開通 >