系列目錄html
首先要聲明,這裏的jq並非批前端框架裏的jquery,而是一個處理json的命令行工具.前端
jq工具相比yq,它更加成熟,功能也更增強大,主要表如今如下幾個方面jquery
支持遞歸查找(我點對咱們平時查看文件很方便)linux
支持條件過濾git
支持控制語句github
支持數組範圍索引正則表達式
這個工具在macos和windows都提供在線包安裝服務,linux並無官方包服務,須要下載後放到usr/bin
目錄下shell
下載地址macos
centos下也能夠經過如下方式安裝編程
wget http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm rpm -ivh epel-release-latest-7.noarch.rpm yum repolist
基本語法格式以下
jq [options] <jq filter> [file...]
須要把文件放在最後面,可是也無所謂,不少時候咱們並不處理本地的json,而是經過標準輸入來處理其它來源類型的json
我本地存有一個叫做test.json的json文件,咱們能夠經過jq . test.json
查看文件裏的全部內容
{ "json": [ "rigid", "better for data interchange" ], "yaml": [ "slim and flexible", "better for configuration" ], "object": { "key": "value", "array": [ { "name": null }, { "name": true }, { "name": 24 } ] }, "paragraph": "Blank lines denote\nparagraph breaks\n", "content": "Or we\ncan auto\nconvert line breaks\nto save space" }
jq輸出的json文件默認都是格式化過的,方便咱們查看
咱們仿照上一節,來獲取json數組裏的全部值.
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .json test.json [ "rigid", "better for data interchange" ]
經過如下命令獲取array數組
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array test.json [ { "name": null }, { "name": true }, { "name": 24 } ]
經過與上節jq相似的命令獲取array裏面的值
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[].name test.json null true 24
數組也能夠在中括號裏面指定索引(跟絕大多數編程語言同樣,從0開始)也與前面的yq相似,不一樣的是這裏可使用[start:end]的方式來索引範圍
上面的例子咱們此次不取所有,只取第0個和第一個
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[0:2] test.json [ { "name": null }, { "name": true } ]
除了索引範圍之後,還能夠索引不連續的對象,語法爲[index1,index2,...]形式
例如,如下操做獲取第零個和第二個對象
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[0,2] test.json { "name": null } { "name": 24 }
以上操做並索引並不必定按照從小到大的順序,好比如下也是能夠的
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .object.array[1,0,2] test.json { "name": true } { "name": null } { "name": 24 }
有時候咱們不肯定一個對象是否存在,這時候咱們能夠在對象後面跟個問號?
來代表不肯定這個對象是否存在
好比jq .yml? test.json
代表你不肯定yml這個屬性在要查詢的對象中是否存在,若是這個對象是不存在的,則返回的值爲null
實際上你會發現,上面不寫問號返回的值也是null,並不會報錯.在這裏體現的不明顯,可是對數組類型的若是一個對象不存在寫爲數組形式就會報錯
好比jq .yml[] test.json
就會出現jq: error (at test.json:25): Cannot iterate over null (null)
錯誤
而使用jq .yml[]? test.json
即使yml對象不存在也不會報錯
,
來取多個對象假如咱們想要同時取json和yaml這兩個對象,可使用,
把兩個命令分開,把它們的結果合在一塊
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq .json,.yaml test.json [ "rigid", "better for data interchange" ] [ "slim and flexible", "better for configuration" ]
上面的使用都逗號的命令裏咱們已經使用兩條命令了,實際工做中可能有更加複雜的命令組合,這時候可使用()來組織.在jq裏使用()和在其它編程語言裏使用相同.
|
在jq裏管道符概念和linux上概念基本相同.能夠把上一個命令的結果做爲下一個命令的輸出.前面的.object.array
也能夠寫做管道模式.object|.array
先用.object
取object的全部對象,而後結果做爲下級管道的輸入值,.array
從管道結果裏取array數組
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '.object|.array' test.json [ { "name": null }, { "name": true }, { "name": 24 } ]
在kubernetes 的jsonpath裏,可使用..來查找子對象,很是方便,唯一很差的是若是子對象包含數組類型則顯示爲Map[xxx]類型,而且展現的結果再也不是json格式,可讀性不是特別好.比較遺憾的是,在jq裏並不支持..
這種語法,而是更爲複雜一些,須要使用管道符.
命令的格式以下
..|.對象名?
首先這裏使用了..表示從根對象開始取,而後使用管道符,後面之因此使用可空對象(對象後面帶問號)是由於它會在每一層都查找,不使用可空對象的話找不到就會報錯.
假如咱們並不知道array對象的上一層是什麼,可是知道這個對象存在.可使用下面命令來獲取.
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '..|.array?' test.json null [ { "name": null }, { "name": true }, { "name": 24 } ] null null null
這裏之因此會出現好多的null,由於jq會進入每一層對象裏面查找,找不到就返回null.爲了展現美觀,咱們也能夠作一些簡的處理
tylerzhou@DESKTOP-OE0CB8G:/mnt/d/test/jqjqtest$ jq '..|.array?' test.json|sed 's/null//g' [ { "name": }, { "name": true }, { "name": 24 } ]
以上命令使用sed把null替換爲空,這裏不夠優雅的地方在於把第一個name的值null也替換爲空了.
這裏的命令外層加了引號,之因此要加引號是由於這個管道是jq管道,若是不加引號就會被shell識別爲shell命令管道,從而致使錯誤.
咱們使用示例來講明,使用如下命令獲取kubernetes集羣中的一個pod的conditions信息
[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]' [ { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:19:28Z", "status": "True", "type": "Initialized" }, { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "Ready" }, { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "ContainersReady" }, { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:19:28Z", "status": "True", "type": "PodScheduled" } ]
如今我想要過濾type
爲Ready
的對象,可使用如下命令
[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type=="Ready")' { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "Ready" }
以上命令把status裏的conditions數組對象作爲輸入傳遞給管道下一級,而後使用select函數裏面傳入條件.
以上是徹底匹配type屬性值爲Ready
,若是想要模糊匹配,則能夠經過管道使用contains函數
[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type|contains("Ready"))' { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "Ready" } { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "ContainersReady" }
這樣,兩個type值包含Ready的所有被選擇出來了.
上面的過濾條件中,因爲Ready
是大寫的,所以不管是相等比較仍是包含比較,都必須使用大寫,若是是小寫則沒法匹配到.可是不少時候咱們可能對大小寫是不清楚的,咱們但願匹配的時候區分大小寫,這在jq裏也是能夠作到的,咱們使用match
函數,match函數爲正則匹配函數.接收一個數組形式的參數,數組的第一項爲要匹配的內容,第二項爲開關(好比g
表明全局開關,i
則表明不區分大小寫)
咱們把上面的示例改造以下
[centos@k8s-master ~]$ kubectl get pod consul-0 -ojson|jq '.status.conditions[]|select(.type|match(["ready","i"]))' { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "Ready" } { "lastProbeTime": null, "lastTransitionTime": "2019-05-14T07:25:06Z", "status": "True", "type": "ContainersReady" }
這樣使用正則表達式咱們就能夠不區分大小寫匹配了.
以上只列出了工做中可能經常使用的功能,詳細功能能夠查看官方文檔