JSON в файл с фиксированной шириной - PullRequest
0 голосов
/ 28 февраля 2011

Я должен извлечь данные из файла JSON в зависимости от конкретного ключа.Затем данные должны быть отфильтрованы (на основе значения ключа) и разделены на разные плоские файлы фиксированной ширины.Мне нужно разработать решение с использованием сценариев оболочки.

Поскольку данные являются просто парой ключ-значение, я могу извлечь их, обработав каждую строку в файле JSON, проверив тип и записав значения в соответствующие фиксированныеширина файла.

Моя проблема в том, что размер входного файла JSON составляет приблизительно 5 ГБ.Мой метод очень прост и хотелось бы знать, есть ли лучший способ добиться этого с помощью сценариев оболочки?

Пример файла JSON будет выглядеть следующим образом:

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

Выше приведенообразец данных, которые мне нужно обработать.

Ответы [ 2 ]

0 голосов
/ 01 марта 2011

скрипт 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
}

соответствующий скрипт оболочки

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

Пример:

$ ./script-name < input_file
$ ls -1 *.out
json_decode_error.out
Mail.out
0 голосов
/ 01 марта 2011

Попробуйте:

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

Я сделал предположения на основе предоставленных образцов данных. Есть много основанных на этих предположениях, которые, возможно, придется изменить, если данные сильно отличаются от того, что вы показали. В частности, этот сценарий не будет работать должным образом, если значения данных или имена полей содержат двоеточия, запятые, кавычки или фигурные скобки. Если это проблема, это одна из основных причин, по которой следует использовать правильный анализатор JSON. Если бы это было мое задание, я бы настойчиво отодвинулся в этом вопросе, чтобы получить разрешение на использование соответствующих инструментов.

Это выводит строки с типом «Mail» в файл с именем «Mail.fixed.out» и типом «Chat» в «Chat.fixed.out» и т. Д.

Имя поля «Тип» и значение поля («Почта» и т. Д.) Не выводятся как часть содержимого. Это можно изменить.

В противном случае выводятся как имена, так и значения полей. Это можно изменить.

Все поля ширины фиксированы в 15 символов, дополнены пробелами, без разделителей. Ширина поля может быть изменена и т. Д.

Дайте мне знать, насколько это близко к тому, что вы ищете, и я могу внести некоторые коррективы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...