Разделите файл на основе шаблона - PullRequest
0 голосов
/ 31 октября 2018

У меня есть вывод JSON, сгенерированный как часть команды curl, и я хочу разделить результирующий файл на основе шаблона:

Содержимое файла выглядит примерно так:

{
"clusters" : [ {
"name" : "subject",
"version" : "XXX",
"services" : [ {
  "name" : "initiator",
  "config" : {
    "items" : [ {
      "name" : "enableSecurity",
      "value" : "true",
      "sensitive" : false
    }, {
      "name" : "service_config_suppression_server_count_validator",
      "value" : "true",
      "sensitive" : false
    } ]
  },
  "roles" : [ {
    "name" : "intiator-role1",
    "type" : "SERVER",
    "hostRef" : {
      "hostId" : "754389-8989db-8743ty"
    },
    "config" : {
      "items" : [ {
        "name" : "role_creds",
        "value" : "sdfujnvhdsg87909",
        "sensitive" : true
      }, {
        "name" : "serverId",
        "value" : "1",
        "sensitive" : false
      } ]
    },
    "roleConfigGroupRef" : {
      "roleConfigGroupName" : "initiator-group"
    }
  } ]
} ]
},
....bunch of lines in between
..........

 {
  "name" : "subject2",
  "version" : "XXX",
"services" : [ {
  "name" : "ingestor",
  "config" : {
    "items" : [ ]
  },
  "roles" : [ {
    "name" : "ingestor-role1",
    "type" : "service",
    "hostRef" : {
      "hostId" : "754389-8989db-8743ty"
    },
    "config" : {
      "items" : [ {
        "name" : "role_code",
        "value" : "sdfujnvhdsg67340",
        "sensitive" : true
      } ]
    },
    "roleConfigGroupRef" : {
      "roleConfigGroupName" : "ingestor-group"
    }
  } ]
  } ]
  }
  ]
  }

Я хочу разбить этот файл на разные файлы всякий раз, когда повторяется строка «версия»: «ХХХ». Таким образом, этот сгенерированный файл должен иметь содержимое, начинающееся с первых двух строк перед строкой до следующего появления строки.

Это просто выдержка из огромного файла json, в этом наборе данных я сохранил только два строковых шаблона, поэтому ожидаю два файла со следующим содержанием:

файл 1 должен иметь:

"clusters" : [ {
"name" : "subject",
"version" : "XXX",
"services" : [ {
  "name" : "initiator",
  "config" : {
    "items" : [ {
      "name" : "enableSecurity",
      "value" : "true",
      "sensitive" : false
    }, {
      "name" : "service_config_suppression_server_count_validator",
      "value" : "true",
      "sensitive" : false
    } ]
  },
  "roles" : [ {
    "name" : "intiator-role1",
    "type" : "SERVER",
    "hostRef" : {
      "hostId" : "754389-8989db-8743ty"
    },
    "config" : {
      "items" : [ {
        "name" : "role_creds",
        "value" : "sdfujnvhdsg87909",
        "sensitive" : true
      }, {
        "name" : "serverId",
        "value" : "1",
        "sensitive" : false
      } ]
    },
    "roleConfigGroupRef" : {
      "roleConfigGroupName" : "initiator-group"
    }
  } ]
} ]
},
....bunch of lines in between
..........

и файл 2 должен иметь

 {
  "name" : "subject2",
  "version" : "XXX",
"services" : [ {
  "name" : "ingestor",
  "config" : {
    "items" : [ ]
  },
  "roles" : [ {
    "name" : "ingestor-role1",
    "type" : "service",
    "hostRef" : {
      "hostId" : "754389-8989db-8743ty"
    },
    "config" : {
      "items" : [ {
        "name" : "role_code",
        "value" : "sdfujnvhdsg67340",
        "sensitive" : true
      } ]
    },
    "roleConfigGroupRef" : {
      "roleConfigGroupName" : "ingestor-group"
    }
  } ]
  } ]
  }
  ]
  }

Хотите достичь этого с помощью bash, желательно awk, заранее.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Если вы хотите разделить файл на новый файл каждый раз, когда «версия» повторяется, начиная и заканчивая двумя строками перед «версией», вы, вероятно, можете сделать что-то вроде этого:

#!/bin/bash
awk '
BEGIN {
    i = 0
}
{   
    prevLn2 = prevLn1
    prevLn1 = currentLn
    currentLn = $0

    if(currentLn ~ /^[ ]{0,}\"version\"/) {
        i++
    }

    if(i > 0) {
        print prevLn2 >> "file" i ".txt"
    }
}
'

Это сохраняет 2 предыдущие строки в переменных prevLn1 и prevLn2, и для каждой строки во входных данных проверяет, соответствует ли текущая строка регулярному выражению ^[ ]{0,}\"version\" - означает начало строки, затем ноль или более пробелов и буквальный текст "версия". Если это соответствует, увеличьте переменную i. Затем добавьте вторую вторую строку к файлу, который назван переменной i.

Сохраните код в файле, например. splitfile.sh и сделайте его исполняемым chmod 755 splitfile.sh. Использование: ./splitfile.sh < jsonfile.txt создаст файлы file1.txt, file2.txt, file3.txt ... в том же каталоге.

0 голосов
/ 31 октября 2018

Я думаю, что в этом случае лучше всего использовать jq. https://stedolan.github.io/jq/download/

jq позволяет манипулировать и запрашивать любой контент JSON.

Обновлен:

Я отредактировал ваш исходный JSON выше, так что это действительно допустимый JSON, и это команды, которые я использовал для получения jq, чтобы дать мне каждый из элементов в массиве clusters:

 jq '.["clusters"] | .[0]' test.json

 jq '.["clusters"] | .[1]' test.json

Конечно, вы можете написать это по своему усмотрению. Нет необходимости искать текст version="XXX", поскольку все они являются просто элементами в массиве clusters.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...