/ / JSON su file a larghezza fissa: json, shell, unix, scripting

JSON su file a larghezza fissa: json, shell, unix, scripting

Devo estrarre i dati dal file JSON a secondasu una chiave specifica. I dati devono quindi essere filtrati (in base al valore della chiave) e separati in file flat a larghezza fissa diversi. Devo sviluppare una soluzione usando lo scripting della shell.

Poiché i dati sono solo chiave: coppia di valori I può estrarli elaborando ciascuna riga nel file JSON, controllando il tipo e scrivendo i valori nel corrispondente file a larghezza fissa.

Il mio problema è che il file JSON di input ha una dimensione di circa 5 GB. Il mio metodo è molto semplice e vorrei sapere se c'è un modo migliore per ottenere questo usando lo scripting della shell?

Il file JSON di esempio sarà simile a quanto segue:

{"Type":"Mail","id":"101","Subject":"How are you ?","Attachment":"true"}
{"Type":"Chat","id":"12ABD","Mode:Online"}

Quanto sopra è un esempio del tipo di dati che devo elaborare.

risposte:

0 per risposta № 1

Fare un tentativo:

#!/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"
}

Ho fatto delle ipotesi basate sui dati di esempiofornito. C'è molto in base a quei presupposti che potrebbero dover essere modificati se i dati variano molto da quello che hai mostrato.In particolare, questo script non funzionerà correttamente se i valori dei dati o i nomi dei campi contengono due punti, virgole, virgolette o parentesi graffe Se questo è un problema, è uno dei motivi principali per cui dovrebbe essere usato un parser JSON appropriato. Se fosse il mio incarico, spingere indietro su questo punto per ottenere il permesso di usare gli strumenti adeguati.

Questo emette linee che hanno tipo "Mail" in un file chiamato "Mail.fixed.out" e digitano "Chat" su "Chat.fixed.out", ecc.

Il nome del campo "Tipo" e il valore del campo ("Mail", ecc.) Non vengono emessi come parte dei contenuti. Questo può essere cambiato.

In caso contrario, vengono visualizzati sia i nomi dei campi che i valori. Questo può essere cambiato.

Le larghezze di campo sono tutte fisse a 15 caratteri, riempite di spazi, senza delimitatori. La larghezza del campo può essere modificata, ecc.

Fammi sapere quanto è vicino a ciò che stai cercando e posso apportare alcune modifiche.


0 per risposta № 2

script 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
}

script di shell corrispondente

#!/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

Esempio:

$ ./script-name < input_file
$ ls -1 *.out
json_decode_error.out
Mail.out