日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jq命令用法总结

發布時間:2024/3/12 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jq命令用法总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

簡介

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

網上的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# 獲取數組中的值 $ echo -n '{"id":1, "name":"zhangsan", "score":[75, 85, 90]}'|jq -r '.score[0]' 75$ echo -n '[75, 85, 90]'|jq -r '.[0]' 75# 數組截取 $ echo -n '[75, 85, 90]'|jq -r '.[1:3]' [85,90 ]# []展開數組 $ 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?'# //符號用于,當前面的表達式取不到值時,執行后面的表達式 $ 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"# 逗號使得可以執行多個jq表達式,使得一個輸入可計算出多個輸出結果 $ echo 1 | jq '., ., .' 1 1 1# 括號用于提升表達式的優先級,如下:逗號優先級低于算術運算 $ $ echo '1'|jq '.+1, .*2' 2 2$ echo '1'|jq '(.+1, .)*2' 4 2# 管道優先級低于逗號 $ echo '1'|jq '., .|tostring' "1" "1"$ echo '1'|jq '., (.|tostring)' 1 "1"

理解jq執行過程

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

  • jq從流中獲取一個json元素
  • jq執行表達式,表達式生成新的json元素
  • jq將新的json元素打印輸出
  • 可以看看這些示例,如下:

    # 這里jq實際上將1 2 3 4當作4個integer元素,每找到一個元素就執行+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數組元素 # 這里理解為jq從流中只取到了1個json元素,這個json元素的類型是數組 $ 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"}

    數據構造

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

    # 使用[]構造數組元素,-n告訴jq沒有輸入數據,直接執行表達式并生成輸出數據 $ 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# 每行分割成數組,[]構造新的數組輸出 $ 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

    基礎函數

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

    過濾、排序、分組函數

    $ 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函數用于過濾,類似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"}# 有一些簡化的過濾函數,如arrays, objects, iterables, booleans, numbers, normals, finites, strings, nulls, values, scalars # 它們根據類型過濾,如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] eof1 "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"}# 根據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}

    字符串操作函數

    # contains函數,判斷是否包含,實際也可用于判斷數組是否包含某個元素 $ 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"# 字符串數組,通過逗號拼接成一個字符串 $ 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# 正則表達式捕獲數據 $ 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"]

    日期函數

    # 當前時間綴 $ jq -n 'now' 1653820640.939947# 將時間綴轉換為0時區的分解時間(broken down time),形式為 年 月 日 時 分 秒 dayOfWeek dayOfYear $ jq -n 'now|gmtime' -c [2022,4,29,10,45,5.466768980026245,0,148]# 將時間綴轉換為本地時區的分解時間(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是一門腳本語言,它也支持變量、分支結構、循環結構與自定義函數,如下:

    $ 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"]# 數組展開式變量定義 $ 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"# 循環結構,第一個表達式條件滿足時,執行只每二個表達式 # 循環結構除了while,還有until、recurse等 $ echo 1|jq 'while(.<100; .*2)' 1 2 4 8 16 32 64# 自定義計算3次方的函數 $ echo 2|jq 'def cube: .*.*. ; cube' 8

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

    輔助shell編程

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

    但jq本身是處理json的,而json中的對象就可等同于Map,json中的數組就可等同于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"; donemap='{}'; #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\n" "$key" "$value"; done # Map的entrySet遍歷 while read -r line; do key=$(jq '.key' -r <<<"$line"); value=$(jq '.value' -r <<<"$line"); printf "%s:%s\n" "$key" "$value"; done <<<$(echo "$map" | jq 'to_entries[]' -c)

    總結

    可以發現,jq已經實現了json數據處理與分析的方方面面,我個人最近在工作中,也多次使用jq來分析調用日志等,用起來確實非常方便。

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

    往期內容

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

    總結

    以上是生活随笔為你收集整理的jq命令用法总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。