2

У меня есть один файл в формате Json, как показано ниже:

    {
        "sources":[{
        "field1":1000,
        "field2":"winevent_log",
        "field3":"winevent_log",
        "field4":"os_security",
        "field5":true,
        "field6":false,
      },{
        "field1":1001,
        "field2":"winperf_cpu",
        "field3":"winperf_cpu",
        "field4":"os_perf",
        "field5":false,
        "field6":false,
      },{
        "field1":1002,
        "field2":"winperf_disk",
        "field3":"winperf_disk",
        "field4":"os_perf",
        "field5":false,
        "field6":false,
      },{
        "field1":1003,
        "field2":"winperf_mem",
        "field3":"winperf_mem",
        "field4":"OS_perf",
        "field5":false,
        "field6":false,
      }
    }

Я пытаюсь разбить его на разные файлы на основе разделителя. Я хотел бы видеть 4 разных файла, как показано ниже:

файл 1:

    {
        "field1":1000,
        "field2":"winevent_log",
        "field3":"winevent_log",
        "field4":"os_security",
        "field5":true,
        "field6":false,
    }

файл 2:

    {
        "field1":1001,
        "field2":"winperf_cpu",
        "field3":"winperf_cpu",
        "field4":"os_perf",
        "field5":false,
        "field6":false,
    }

И так далее.

Я попытался с помощью команд csplit и awk:

    csplit input_file '/"id"/' '{*}'
    awk '/,{/{n++}{print >"out" n ".json" }' input_file

Но я не получил выходные_файлы так, как я ожидал, потому что разделитель разбит на несколько строк и начинается в середине одной строки.

Кто-нибудь знает, как использовать awk или csplit таким образом, чтобы начальный разделитель был "{newline" field1 "", а конечный разделитель - "},"

2 ответа2

1

Используйте адрес диапазона (как в sed) и вставьте обратно { и } с помощью sprintf

awk '/field1/,/field6/ {if ($0 ~ /field1/) {i++;$0=sprintf("    {\n%s",$0)}; if ($0 ~ /field6/) {$0=sprintf("%s\n    }",$0)}; print > ("file" i)}' input_file

Есть несколько статических строк, если они изменятся, вы можете заменить их на Regex.

1

Предполагая, что разделителем в вашем случае является },{ , вы можете использовать ex editor (часть Vim), чтобы разделить файл, например:

ex +%j +'%s/},{/},\r{/g' +'g/./exe ".w! file".line(".").".txt"' -scq! -V1 file.txt

который объединит все строки (%j), заменит (%s) содержимое, заменив },{ новой строкой (\r), а затем запишет каждую строку в отдельный файл на основе номера текущей строки. Недостатком является то, что ваша составная часть находится в одной строке, но вы можете снова разделить ее запятой. Для более подробной информации, проверьте: Как записать каждую строку в отдельный файл?

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .