Verwenden von sed zum Komprimieren von JSON-Arrays

641
xpt

Ich habe eine JSON-Ausgabe im folgenden Format:

{ "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 ] } 

Da ich das Programm, das es ausgegeben hat, nicht ändern kann, muss ich JSON-Arrays selbst verwenden sed(oder awk). Die wünschenswerte Ausgabe wäre:

{ "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] } 

Ich habe selbst versucht, ein sedSkript zu erstellen, aber es ist nur halb gekocht und funktioniert nicht vollständig:

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

Bitte helfen Vielen Dank.

2
Ich denke, `sed` ist nicht das beste Werkzeug für dieses Problem. Sie sollten einen JSON-Parser / Formatierer ausprobieren, beispielsweise "jq" (https://stedolan.github.io/jq/). Vielleicht möchten Sie https://stackoverflow.com/questions/9105031/how-to-beautify-json-in-python-or-through-command-line und https://stackoverflow.com/questions/352098/how überprüfen -can-i-pretty-print-json-in-unix-shell-script uzsolt vor 6 Jahren 1
FYI, die Ausgabe, an der ich arbeiten wollte, wird genau von "jq", einem "C" -Programm erstellt. Daher interessieren mich keine Python-Lösungen. @uzsolt. Was Sie hier sehen, ist nur eine ausgewählte Darstellung der 4 ~ 6M-Ausgabe, die ich habe. Wenn Sie den obigen Befehl "sed" nicht verstehen, ist es unangebracht, zu beurteilen, ob "sed" das beste Werkzeug ist oder nicht. xpt vor 6 Jahren 0
Also, was willst du genau? Sie möchten '\ n' (nach einem Komma) löschen *, wenn * wir in eckigen Klammern (`[` und `]`) stehen. Wenn Sie wollen, tun Sie es mit `sed` einfach! Es ist nicht unmöglich, aber "FYI" gibt es bessere Werkzeuge. Ich bin neugierig auf die "sed" -Weglösung. Tue es! (Jemand hat Ihre Frage abgelehnt - FYI, nicht ich) uzsolt vor 6 Jahren 0
Danke für die Eingabe @uzsolt. OK, ich habe bekommen. Ich werde `sed` vergessen und dann in` awk` machen. xpt vor 6 Jahren 0
Das Down-Voting zeigt nichts, aber es gibt Engstirnige und gemeine Leute in freier Wildbahn. Ich mache es in "awk" und poste zurück. xpt vor 6 Jahren 0
Ich denke, "awk" ist besser * in diesem Fall * :) uzsolt vor 6 Jahren 0

1 Antwort auf die Frage

3
Paulo

I edited your sed, hope this helps.

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 }' 
OH MEIN GOTT! Das ist erstaunlich. Ich wurde von den Leuten davon abgehalten, "sed" aufzugeben, aber tief in meinem Kopf glaube ich immer noch, dass "sed" es kann, und ... BANG! hier ist deine unglaublich einfache Lösung, die einwandfrei funktioniert !!! Bitte nimm meine insgesamt +50 Punkte als herzlichen Willkommen bei Superuser! xpt vor 6 Jahren 0
Ich glaube, ich verstehe fast alles, aber wie die Schleifen enden. Würden Sie das bitte näher ausführen? xpt vor 6 Jahren 0
Nun wünschte ich mir, ich hätte mehr Down-Votes für diese Frage - offensichtlich haben sie Down-Votes gewählt, weil sie nicht glauben, dass es eine "sed" -Lösung geben wird, sogar in ihren wildesten Vorstellungen. Für alle diese Leute zeigt diese ausgezeichnete Antwort, wie eng Sie in Ihrem Gesicht sind. xpt vor 6 Jahren 0
Ich kann meine +50 Kopfgeld nur innerhalb von 23 Stunden vergeben, nimm also meine +25 Punkte. xpt vor 6 Jahren 0
Ich habe es aus dem Mann `T-Label` herausgefunden:" _If nein /// hat erfolgreich eine Ersetzung gemacht, seit die letzte Eingabezeile gelesen wurde und seit dem letzten `t'- oder` T'-Befehl, dann zu verzweigt Etikette_" xpt vor 6 Jahren 0
Entschuldigen Sie, ich weiß nicht viel, wie das "Punkte-Zeug" funktioniert, aber ich danke Ihnen vielmals für die Punkte. Zum Schluss habe ich genug Punkte zum Kommentieren :) Danke. Ja, Sie haben recht, der 'T'-Befehl erledigt die Aufgabe, wenn Sie zu der' A'-Bezeichnung springen, wenn sich kein ']' im Musterbereich befindet. Alle Befehle werden nur angewendet, wenn sed eine Zeile mit der Adresse '/ \ [$ /' findet. Andere Zeilen werden ohne Ausgabe gedruckt. Paulo vor 6 Jahren 0
Schöne Antwort, aber ich schlage vor, Sie fügen einen Erklärungsabschnitt mit einer Aufschlüsselung des Befehls hinzu, um die Funktionsweise zu veranschaulichen. Es scheint, dass Sie einige `sed'-Funktionen verwenden, mit denen nicht jeder vertraut ist. simlev vor 6 Jahren 1
Obwohl dies die Frage beantworten kann, wäre es eine bessere Antwort, wenn Sie eine Erklärung liefern könnten, warum dies so ist. DavidPostill vor 6 Jahren 0
Zur Erläuterung hinzugefügt. Informationen zu GNU-sed-Befehlen finden Sie unter 'info sed'. ps entschuldige mich für englische Fehler. Paulo vor 6 Jahren 0