使用 jq 为 json 对象中的每个数组元素生成一行输出,该对象还包括 json 对象中的其他字段

Using jq to produce one line of output per array element in a json object that also includes other fields from the json object

我正在尝试格式化一些由 json 对象组成的数据,这些对象包括一些识别信息以及一个或多个 json 对象的数组,我希望结果是一个每个数组元素的数据行,其中每行应包含数组元素中的一些字段和标识信息中的一些字段。

我的示例数据如下:

{
  "eventCreation": {
    "timeStamp": "2020-06-06T15:07:20Z",
    "epoch": 1591456040
  },
  "eventData": {
    "applName": "SampleApp",
    "channelName": "SYSTEM.DEF.SVRCONN",
    "connectionName": "127.0.0.1",
    "channelType": "Svrconn",
    "remoteProduct": "MQJM",
    "remoteVersion": "09010005",
    "activityTrace": [
      {
        "operationId": "Get",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 102,
        "reasonCode": {
          "name": "No Msg Available",
          "value": 2033
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      },
      {
        "operationId": "Cb",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 10,
        "reasonCode": {
          "name": "None",
          "value": 0
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      },
      {
        "operationId": "Cb",
        "operationTime": "11:07:18",
        "qmgrOpDuration": 12,
        "reasonCode": {
          "name": "None",
          "value": 0
        },
        "objectName": "SYSTEM.DEFAULT.LOCAL.QUEUE"
      }
    ]
  }
}

我想得到这样的输出:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Get",102,"SYSTEM.DEFAULT.LOCAL.QUEUE",2033
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",10,"SYSTEM.DEFAULT.LOCAL.QUEUE",0
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","11:07:18","Cb",12,"SYSTEM.DEFAULT.LOCAL.QUEUE",0

我可以选择数组中的任何一个元素并让它打印 3 行,但如果我添加第二个元素,它将打印 9 行,第三个元素打印 27 行,等等。

例如:

jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId}|[.[]]|@csv' TEST.json

会产生这个:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb"

如果我像这样添加第二个:

jq -r '{channelName: .eventData.channelName, channelType: .eventData.channelType, connectionName: .eventData.connectionName, applName: .eventData.applName, remoteProduct: .eventData.remoteProduct, remoteVersion: .eventData.remoteVersion, operationId: .eventData.activityTrace[].operationId, qmgrOpDuration: .eventData.activityTrace[].qmgrOpDuration}|[.[]]|@csv' TEST.json

会产生这个:

"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Get",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",102
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",10
"SYSTEM.DEF.SVRCONN","Svrconn","127.0.0.1","SampleApp","MQJM","09010005","Cb",12

使用您的方法,解决方案如下:

.eventData
| ({channelName, channelType, connectionName, applName, remoteProduct, remoteVersion}
   + ( .activityTrace[]
       | { operationTime, operationId, qmgrOpDuration, objectName, v: .reasonCode.value}))
| [.[]]
| @csv

关键是只迭代一次。

另请注意,此解决方案部分地通过使用 {foo: .foo} 可以缩写为 {foo}.

这一事实来实现其简洁性

一种稍微更有效的方法

.eventData
| [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion]
  + ( .activityTrace[]
      | [.operationTime, .operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
| @csv

.operationTime first

.eventData
| [.channelName, .channelType, .connectionName, .applName, .remoteProduct, .remoteVersion] as $x
| ( .activityTrace[] 
    | [.operationTime]
      + $x
      + [.operationId, .qmgrOpDuration, .objectName, .reasonCode.value] )
| @csv