W zależności od tego muszę wyodrębnić dane z pliku JSONna konkretny klucz. Dane muszą być następnie filtrowane (na podstawie wartości klucza) i rozdzielane na różne pliki o stałej szerokości. Muszę opracować rozwiązanie przy użyciu skryptów powłoki.
Ponieważ dane to tylko para klucz: wartość, mogę je wyodrębnić, przetwarzając każdą linię w pliku JSON, sprawdzając typ i zapisując wartości w odpowiednim pliku o stałej szerokości.
Moim problemem jest to, że wejściowy plik JSON ma rozmiar około 5 GB. Moja metoda jest bardzo prosta i chciałbym wiedzieć, czy istnieje lepszy sposób na osiągnięcie tego za pomocą skryptów powłoki?
Przykładowy plik JSON wyglądałby jak poniżej:
{"Type":"Mail","id":"101","Subject":"How are you ?","Attachment":"true"}
{"Type":"Chat","id":"12ABD","Mode:Online"}
Powyższe jest przykładem rodzaju danych, które muszę przetworzyć.
Odpowiedzi:
0 dla odpowiedzi № 1Wypróbuj to:
#!/usr/bin/awk
{
line = ""
gsub("[{}x22]", "", $0)
f=split($0, a, "[:,]")
for (i=1;i<=f;i++)
if (a[i] == "Type")
file = a[++i]
else
line = line sprintf("%-15s",a[i])
print line > file ".fixed.out"
}
Założyłem założenia na podstawie przykładowych danychopatrzony. Wiele opiera się na tych założeniach, które mogą wymagać zmiany, jeśli dane różnią się znacznie od tego, co pokazałeś. W szczególności skrypt ten nie będzie działać poprawnie, jeśli wartości danych lub nazwy pól zawierają dwukropki, przecinki, cudzysłowy lub nawiasy klamrowe Jeśli jest to problem, jest to jeden z głównych powodów, dla których należy użyć właściwego parsera JSON. Gdyby to było moje zadanie, nacisnąłem mocno w tym punkcie, aby uzyskać pozwolenie na użycie odpowiednich narzędzi.
Wyprowadza wiersze, które mają typ „Mail” do pliku o nazwie „Mail.fixed.out” i wpisz „Chat” do „Chat.fixed.out” itd.
Nazwa pola „Typ” i wartość pola („Poczta” itp.) Nie są wyświetlane jako część zawartości. Można to zmienić.
W przeciwnym razie wyświetlane są zarówno nazwy pól, jak i wartości. Można to zmienić.
Wszystkie szerokości pól są ustalone na 15 znaków, wypełnione spacjami, bez ograniczników. Szerokość pola można zmienić itp.
Daj mi znać, jak blisko jest tego, czego szukasz i mogę dokonać pewnych zmian.
0 dla odpowiedzi nr 2
skrypt perl
#!/usr/bin/perl -w
use strict;
use warnings;
no strict "refs"; # for FileCache
use FileCache; # avoid exceeding system"s maximum number of file descriptors
use JSON;
my $type;
my $json = JSON->new->utf8(1); #NOTE: expect utf-8 strings
while(my $line = <>) { # for each input line
# extract type
eval { $type = $json->decode($line)->{Type} };
$type = "json_decode_error" if $@;
$type ||= "missing_type";
# print to the appropriate file
my $fh = cacheout ">>", "$type.out";
print $fh $line; #NOTE: use cache if there are too many hdd seeks
}
odpowiedni skrypt powłoki
#!/bin/bash
#NOTE: bash is used to create non-ascii filenames correctly
__extract_type()
{
perl -MJSON -e "print from_json(shift)->{Type}" "$1"
}
__process_input()
{
local IFS=$"n"
while read line; do # for each input line
# extract type
local type="$(__extract_type "$line" 2>/dev/null ||
echo json_decode_error)"
[ -z "$type" ] && local type=missing_type
# print to the appropriate file
echo "$line" >> "$type.out"
done
}
__process_input
Przykład:
$ ./script-name < input_file
$ ls -1 *.out
json_decode_error.out
Mail.out