簡體   English   中英

使用jq刪除嵌套數組的匹配/非匹配元素

[英]Remove matching/non-matching elements of a nested array using jq

我需要將sonarqube分析歷史記錄的結果拆分為單個文件。 假設下面有一個開始輸入,

    {
  "paging": {
    "pageIndex": 1,
    "pageSize": 100,
    "total": 3
  },
  "measures": [
    {
      "metric": "coverage",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "100.0"
        },
        {
          "date": "2018-11-21T12:22:39+0000",
          "value": "100.0"
        },
        {
          "date": "2018-11-21T13:09:02+0000",
          "value": "100.0"
        }
      ]
    },
    {
      "metric": "bugs",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "0"
        },
        {
          "date": "2018-11-21T12:22:39+0000",
          "value": "0"
        },
        {
          "date": "2018-11-21T13:09:02+0000",
          "value": "0"
        }
      ]
    },
    {
      "metric": "vulnerabilities",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "0"
        },
        {
          "date": "2018-11-21T12:22:39+0000",
          "value": "0"
        },
        {
          "date": "2018-11-21T13:09:02+0000",
          "value": "0"
        }
      ]
    }
  ]
}

如何使用jq清除結果,以便它只保留每個元素的歷史數組條目? 所需的輸出是這樣的(輸出20181118123808.json用於“2018-11-18T12:37:08 + 0000”的分析):

{
  "paging": {
    "pageIndex": 1,
    "pageSize": 100,
    "total": 3
  },
  "measures": [
    {
      "metric": "coverage",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "100.0"
        }
      ]
    },
    {
      "metric": "bugs",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "0"
        }
      ]
    },
    {
      "metric": "vulnerabilities",
      "history": [
        {
          "date": "2018-11-18T12:37:08+0000",
          "value": "0"
        }
      ]
    }
  ]
}

我迷失了如何僅在子元素上操作同時保持父結構完整。 JSON文件的命名將從jq實用程序外部處理。 提供的樣本數據將分為3個文件。 其他一些輸入可以有可變數量的條目,有些可能高達10000.謝謝。

這是一個使用awk編寫不同文件的解決方案。 該解決方案假定每個度量的日期相同且順序相同,但對不同日期的數量或不同度量的數量沒有限制。

jq -c 'range(0; .measures[0].history|length) as $i
  | (.measures[0].history[$i].date|gsub("[^0-9]";"")),  # basis of filename
    reduce range(0; .measures|length) as $j (.;
      .measures[$j].history |= [.[$i]])' input.json |
awk -F\\t 'fn {print >> fn; fn="";next}{fn="output-" $1 ".json"}'

評論

awk的選擇只是為了方便。

這種方法的缺點是,如果要對每個文件進行整齊格式化,則每個文件都需要額外運行漂亮的打印機(例如jq)。 因此,如果要求每個文件中的輸出都是整潔的,則可以為每個日期運行jq一次,從而避免了對后處理( awk )步驟的需要。

如果措施的日期不是鎖定步驟,​​那么仍然可以使用與上述相同的方法,但當然,收集日期和相應的措施必須以不同方式進行。

產量

上面調用jq產生的前兩行如下:

"201811181237080000"
{"paging":{"pageIndex":1,"pageSize":100,"total":3},"measures":[{"metric":"coverage","history":[{"date":"2018-11-18T12:37:08+0000","value":"100.0"}]},{"metric":"bugs","history":[{"date":"2018-11-18T12:37:08+0000","value":"0"}]},{"metric":"vulnerabilities","history":[{"date":"2018-11-18T12:37:08+0000","value":"0"}]}]}

在評論中,出現了原始問題的以下附錄:

是否存在一種變化,其中過濾是基於日期值而不是位置? 不能保證訂單是相同的,或者每個度量中的元素數量將是相同的(即一些日期可能缺少“錯誤”,一些可能具有額外的度量,例如“復雜性”)。

以下將生成一個JSON對象流,每個日期一個。 此流可以使用我之前的答案中的日期進行注釋,該日期顯示如何使用這些注釋來創建各種文件。 為了便於理解,我們使用了兩個輔助函數:

def dates:
  INDEX(.measures[].history[].date; .)
  | keys;

def gather($date): map(select(.date==$date));

dates[] as $date
| .measures |= map( .history |= gather($date) )

INDEX / 2

如果你的jq沒有INDEX/2 ,那么現在是升級的絕佳時機,但是如果不可行的話,這就是它的def:

def INDEX(stream; idx_expr):
  reduce stream as $row ({};
    .[$row|idx_expr|
      if type != "string" then tojson
      else .
      end] |= $row);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM