Использование sed для сжатия массивов JSON

594
xpt

У меня есть вывод JSON в следующем формате:

{ "DaysCfg": { "Range": { "lowerDate": "2017-07-28T00:00:00.000-04:00", "upperDate": "2017-08-04T00:00:00.000-04:00" }, "DaysInPeriod": 8, "DaysToSchedule": [ 0, 1, 2, 3, 4, 5, 6 ] }, "DepartmentsID": [ 138837, 139734, 141934, 142436, 149687, 151049 ], "EmployeesID": [ 5039, 5170, 5889, 6051, 6236, 7208, 7281, 8776, 8781, 8936, 9261 ], "EndDate": "2017-08-03T23:59:00.000-04:00", "IntervalSize": 15, "IsActivitiesEnabled": true, "ModifyExisting": false, "OrignId": 134721, "PrimaryOption": 0, "SchoolDays": [], "ScChanges": [], "StartDate": "2017-07-28T00:00:00.000-04:00", "ZonesToSchedule": [ 5, 4, 6, 3, 3, 3, 2, 14 ] } 

Поскольку я не могу изменить программу, которая ее выводит, я должен использовать sed(или awk) для сжатия JSON-массивов самостоятельно. Желаемый результат будет:

{ "DaysCfg": { "Range": { "lowerDate": "2017-07-28T00:00:00.000-04:00", "upperDate": "2017-08-04T00:00:00.000-04:00" }, "DaysInPeriod": 8, "DaysToSchedule": [0, 1, 2, 3, 4, 5, 6] }, "DepartmentsID": [138837, 139734, 141934, 142436, 149687, 151049], "EmployeesID": [5039, 5170, 5889, 6051, 6236, 7208, 7281, 8776, 8781, 8936, 9261], "EndDate": "2017-08-03T23:59:00.000-04:00", "IntervalSize": 15, "IsActivitiesEnabled": true, "ModifyExisting": false, "OrignId": 134721, "PrimaryOption": 0, "SchoolDays": [], "ScChanges": [], "StartDate": "2017-07-28T00:00:00.000-04:00", "ZonesToSchedule": [5, 4, 6, 3, 3, 3, 2, 14] } 

Я пытался придумать sedсценарий сам, но он только наполовину приготовлен и не полностью работает:

sed -r -e :a -e '/^ *[]}],*$/!N; /": \[/s/\n +//; ta' -e 'P;D' 

Пожалуйста помоги. Спасибо.

2
Я думаю, что `sed` не лучший инструмент для решения этой проблемы. Вы должны попробовать какой-нибудь JSON-парсер / форматер, например `jq` (https://stedolan.github.io/jq/). Может быть, вы хотите проверить https://stackoverflow.com/questions/9105031/how-to-beautify-json-in-python-or-through-command-line и https://stackoverflow.com/questions/352098/how -может-я-очень-печати в формате JSON-в-UNIX-оболочки-скрипта uzsolt 6 лет назад 1
К вашему сведению, вывод, над которым я хотел поработать, создается именно `jq`, программой` C`, поэтому я не заинтересован в каких-либо решениях Python. @uzsolt. То, что вы видите здесь, является только выбранным представлением 4 ~ 6М выхода, который у меня есть. Если вы не понимаете вышеприведенную команду `sed`, то вам неуместно решать, является ли` sed` лучшим инструментом или нет. xpt 6 лет назад 0
Итак, что именно вы хотите? Вы хотите удалить '\ n' (после запятой) *, если * мы заключены в скобки (`[` и `]`). Если вы хотите сделать это с помощью `sed`, просто сделайте это! Это не невозможно, но "К вашему сведению", есть лучшие инструменты. Мне любопытно, что такое "sed"-way. Действуй! (Кто-то отклонил ваш вопрос - к вашему сведению, не я) uzsolt 6 лет назад 0
Спасибо за ввод @uzsolt. ОК, я понял. Я забуду о `sed` и сделаю это в` awk` тогда. xpt 6 лет назад 0
Понижающее голосование ничего не показывает, но есть ограниченные и подлые люди в дикой природе. Я сделаю это в `awk` и отправлю обратно. xpt 6 лет назад 0
Я думаю, что "awk" лучше * в этом случае * :) uzsolt 6 лет назад 0

1 ответ на вопрос

3
Paulo

Я редактировал ваш седь, надеюсь, это поможет.

sed -r '/\[$/ {:a;N;s/\]/&/;Ta;s/\n +//g}'  sed -r '  # sed will apply the commands between '{}' only to lines that matches the address '/\[$/'. /\[$/ {  # Set a mark with label 'a'. :a  # N command, it appends a '\n' to the pattern space, # reads the next line of the input (file,stdin) and appends it to the pattern space. N  # Substitute ']' for itself. If the substitution isn't made (if there isn't a ']' on the # pattern space), the 'T' command jumps to the 'a' label. # Here is the loop to put some lines (or all lines of a file) in the same line. # While there isn't a ']' in the pattern space (which is the last line OP wants to put # on the same line), sed will append '\n<next line>' to the pattern space. s/\]/&/ Ta  # When the substitution is made, sed leaves the loop and applies other commands. # Substitute all occurrences (g flag) of new line character (with any # spaces after) for nothing. s/\n +//g }' 
О, МОЙ БОГ! Это восхитительно. Меня отговаривали люди отказаться от `sed`, но в глубине души я все еще верю, что` sed` может это сделать, и ... БАХ! вот ваше невероятное простое решение, которое работает без нареканий !!! Пожалуйста, получите мои +50 баллов в качестве теплого приветствия суперпользователю! xpt 6 лет назад 0
Я думаю, что я понимаю почти все, но как заканчивается цикл. Не могли бы вы уточнить, пожалуйста? xpt 6 лет назад 0
Теперь я хотел бы, чтобы у меня было больше отрицательных голосов за этот вопрос - очевидно, что они проголосовали отрицательно, потому что они не верят, что будет "sed" решение, даже в их самом смелом воображении. Для всех этих людей этот превосходный ответ показывает, насколько вы ограничены в своем лице. xpt 6 лет назад 0
Я могу получить награду в размере +50 только за 23 часа, так что наберите +25 баллов. xpt 6 лет назад 0
Я сам понял это из man `T label`:" _Если no `s ///` не выполнила успешную подстановку с тех пор, как была прочитана последняя строка ввода, и после последней команды `t` или` T`, перейдите к этикетка_" xpt 6 лет назад 0
Прошу прощения, я не знаю, как работают «очки», но большое спасибо за очки. Наконец, у меня достаточно очков, чтобы комментировать :) спасибо. Да, вы правы, команда 'T' делает все возможное, чтобы перейти к метке 'a', если в области шаблона нет ни одного ']. Все команды применяются только тогда, когда sed находит строку с адресом '/ \ [$ /', остальные строки печатаются без какой-либо редакции. Paulo 6 лет назад 0
Хороший ответ, но я предлагаю вам добавить раздел объяснения с разбивкой команды, чтобы проиллюстрировать, как она работает. Похоже, вы используете некоторую функциональность `sed`, с которой не все знакомы. simlev 6 лет назад 1
Хотя это может ответить на вопрос, было бы лучше ответить, если бы вы могли дать какое-то объяснение ** почему ** это так. DavidPostill 6 лет назад 0
Отредактировано, чтобы добавить объяснение. Смотрите 'info sed' для команд GNU-sed. ps- извините за английские ошибки. Paulo 6 лет назад 0