text+tsv 파일에서 json 생성

text+tsv 파일에서 json 생성

저는 초보자이고 JSon을 사용해본 적이 없습니다. 일부 json 텍스트 파일만 구문 분석했습니다.
카테고리 수는 다를 수 있습니다.

Category1
1111|2222|3333|444|5555
6666|7777|8888|9999|1111
0000|1111|22222|3333|4444
Category2
2222|3333||5555
2222|3333|4444||5555
Category3
AAAA|||BBBB
CCCC|DDDD|EEEE|FFFF|GGGG

예상 JSON: 카테고리 ---> 배열 ---> 각 tsv에 대해 --> Make Key:Value(Year|Title|Name|Format|Base) tsv 값이 위 항목 중 하나와 맞지 않으면 null을 추가하세요. Json은 다음과 같이 해야 합니다. 이것은 각 카테고리를 수치적으로 색인화하고 카테고리를 다시 색인화하여 tsv 배열을 얻을 수 있다는 것입니다.

Json 구조는 다음과 같아야 합니다. 예를 들면 다음과 같습니다.

1) I could get list of category using jq
cat file | jq
Output:
Category1
Category2
Category3
2) Index that Category
jq '.| Category[0]'
Output:
Category1
1111|2222|3333|444|5555
6666|7777|8888|9999|1111
0000|1111|22222|3333|4444


3) Index each tsv 
jq Category1 | jq '.[0]' ---> 
{
"Year": "1111"
"Title": "2222"
"Name": "3333"
"Format": "4444"
"Base": "5555"
}

jq'.|범주[0]

답변1

최종 JSON 문서가 어떻게 보일지 잘 모르겠지만 다음에서는 mlrMiller( ) 및 다음을 사용하여 CSV 입력 파일을 기반으로 JSON 문서를 만듭니다 jq.

mlr --c2j -N --ifs pipe --ragged \
        label Year,Title,Name,Format,Base then \
        put '
                if (NF == 1) {
                        @Category = string($Year)
                } else {
                        $Category = @Category
                }' then \
        filter -x 'is_absent($Category)' then \
        unsparsify file.csv |
jq -n 'reduce inputs as $a ({}; .[$a.Category] += [$a])'

이는 질문에서 언급한 순서대로 언급한 제목을 추가하는 것부터 시작됩니다. Year레코드에 필드가 하나만 있는 경우 해당 필드(첫 번째 필드)의 값을 기억합니다. Category필드가 여러 개인 경우 기억된 값으로 필드가 생성됩니다.

그런 다음 해당 필드가 없는 모든 레코드를 삭제 Category하고 마지막으로 누락된 필드에 null 값을 추가합니다.

이제 JSON 객체 세트가 생겼습니다.

{ "Year": 1111, "Title": 2222, "Name": 3333, "Format": 444, "Base": 5555, "Category": "Category1" }
{ "Year": 6666, "Title": 7777, "Name": 8888, "Format": 9999, "Base": 1111, "Category": "Category1" }
{ "Year": 0000, "Title": 1111, "Name": 22222, "Format": 3333, "Base": 4444, "Category": "Category1" }
{ "Year": 2222, "Title": 3333, "Name": "", "Format": 5555, "Base": "", "Category": "Category2" }
{ "Year": 2222, "Title": 3333, "Name": 4444, "Format": "", "Base": 5555, "Category": "Category2" }
{ "Year": "AAAA", "Title": "", "Name": "", "Format": "BBBB", "Base": "", "Category": "Category3" }
{ "Year": "CCCC", "Title": "DDDD", "Name": "EEEE", "Format": "FFFF", "Base": "GGGG", "Category": "Category3" }

jq그런 다음 필드의 값을 기반으로 객체를 배열로 수집하는 에 의해 처리 됩니다 Category.

데이터가 주어지면 이것은 뭔가를 산출합니다동등하다

{
   "Category1": [
      { "Base": 5555, "Category": "Category1", "Format": 444, "Name": 3333, "Title": 2222, "Year": 1111 },
      { "Base": 1111, "Category": "Category1", "Format": 9999, "Name": 8888, "Title": 7777, "Year": 6666 },
      { "Base": 4444, "Category": "Category1", "Format": 3333, "Name": 22222, "Title": 1111, "Year": 0 }
   ],
   "Category2": [
      { "Base": "", "Category": "Category2", "Format": 5555, "Name": "", "Title": 3333, "Year": 2222 },
      { "Base": 5555, "Category": "Category2", "Format": "", "Name": 4444, "Title": 3333, "Year": 2222 }
   ],
   "Category3": [
      { "Base": "", "Category": "Category3", "Format": "BBBB", "Name": "", "Title": "", "Year": "AAAA" },
      { "Base": "GGGG", "Category": "Category3", "Format": "FFFF", "Name": "EEEE", "Title": "DDDD", "Year": "CCCC" }
   ]
}

이것을 통과하면 jq '.Category1[0]'다음을 얻을 수 있습니다.

{
  "Year": 1111,
  "Title": 2222,
  "Name": 3333,
  "Format": 444,
  "Base": 5555,
  "Category": "Category1"
}

답변2

표준 도구에 비해 데이터에 자유 형식이 너무 많습니다. 예를 들어 Perl을 사용하는 것이 좋습니다.

#!/bin/perl
use JSON::PP;

open(IN, "<file.tsv");
while(<IN>) {
  chomp;
  if (/Category1/) {
     $group = $_;
     @heads = ("Year", "Title", "Name", "Format", "Base");
  } elsif (/Category2/) {
     $group = "new name for Category2";
     @heads = ("Year", "Title", "Name");
  } elsif (/Category3/) {
     $group = $_;
     @heads = ("ABC", "EFD");
  } else {
     my @columns = split /\|/;
     my %row = ();
     for (my $i=0; $i < scalar(@heads); $i++) {
        $row{$heads[$i]} = $columns[$i];
     }
     push @{$data{$group}}, \%row;

  }
}
close(IN);

print encode_json \%data;

답변3

csplit이를 사용하고 수행하는 한 가지 방법이 있습니다 jq.

다음과 같이 데이터를 임시 파일로 분할할 수 있습니다.

csplit -z infile.csv '/^Category/' '{*}'

xx*파일을 JSON 객체로 변환 :

for f in xx*; do
  <$f jq -sRrc '
  split("\n")
  | .[0] as $category
  | .[1:-1]
  | map(split("|"))
  | map({"Year"  : .[0],
         "Title" : .[1],
         "Name"  : .[2],
         "Format": .[3],
         "Base"  : .[4],
        }) | { ($category): . }
  '
done

산출:

{"Category1":[{"Year":"1111","Title":"2222","Name":"3333","Format":"444","Base":"5555"},{"Year":"6666","Title":"7777","Name":"8888","Format":"9999","Base":"1111"},{"Year":"0000","Title":"1111","Name":"22222","Format":"3333","Base":"4444"}]}
{"Category2":[{"Year":"2222","Title":"3333","Name":"","Format":"5555","Base":null},{"Year":"2222","Title":"3333","Name":"4444","Format":"","Base":"5555"}]}
{"Category3":[{"Year":"AAAA","Title":"","Name":"","Format":"BBBB","Base":null},{"Year":"CCCC","Title":"DDDD","Name":"EEEE","Format":"FFFF","Base":"GGGG"}]}

다음과 같은 카테고리를 얻을 수 있습니다.

jq -r 'keys[]'

산출:

Category1
Category2
Category3

다음과 같은 특정 카테고리를 원하는 경우:

n=2; cat xx$(printf "%02d" $((n-1)))

산출:

Category2
2222|3333||5555
2222|3333|4444||5555

인덱스별로 특정 항목을 가져옵니다. 예를 들어 두 번째 객체는 다음과 같습니다 Category2.

jq '.Category2 // empty | .[1]'

산출:

{
  "Year": "2222",
  "Title": "3333",
  "Name": "4444",
  "Format": "",
  "Base": "5555"
}

답변4

#!/usr/bin/perl

use JSON;
use strict;

my @fields = qw(Year Title Name Format Base);
my (%data, $category, $row);

while(<>) {
  chomp;
  my @line = split /\|/;

  if ($#line == 0) {
    # there are no field separators on this line, so
    # this must be a "category" line.
    $category = $_;
    $row = 0;

  } else {
    foreach my $i (0..$#fields) {
      # treat empty strings as null values
      undef $line[$i] if ($line[$i] eq "");

      $data{$category}[$row]{$fields[$i]} = $line[$i]
    };
    $row++;
  };
};

my $json = JSON->new->pretty->canonical;
print $json->encode(\%data) ;

그런데 "pretty"는 json 문자열에서 줄바꿈과 들여쓰기를 활성화합니다. 'canonical'은 키가 정렬된 순서로 출력되도록 합니다(그렇지 않으면 perl 해시가 본질적으로 순서가 없기 때문에 키가 실행될 때마다 반 무작위 순서로 출력됩니다). 둘 다 기본적으로 비활성화되어 있습니다.JSON모듈은 추가 처리 오버헤드를 발생시키고(즉, 속도가 느려짐) 사람이 출력을 읽으려는 경우에만 필요하기 때문입니다. json 데이터를 처리하는 프로그램은 키 순서에 신경 쓰지 않습니다.

샘플 데이터를 출력용 입력으로 사용합니다.

{
   "Category1" : [
      {
         "Base" : "5555",
         "Format" : "444",
         "Name" : "3333",
         "Title" : "2222",
         "Year" : "1111"
      },
      {
         "Base" : "1111",
         "Format" : "9999",
         "Name" : "8888",
         "Title" : "7777",
         "Year" : "6666"
      },
      {
         "Base" : "4444",
         "Format" : "3333",
         "Name" : "22222",
         "Title" : "1111",
         "Year" : "0000"
      }
   ],
   "Category2" : [
      {
         "Base" : null,
         "Format" : "5555",
         "Name" : null,
         "Title" : "3333",
         "Year" : "2222"
      },
      {
         "Base" : "5555",
         "Format" : null,
         "Name" : "4444",
         "Title" : "3333",
         "Year" : "2222"
      }
   ],
   "Category3" : [
      {
         "Base" : null,
         "Format" : "BBBB",
         "Name" : null,
         "Title" : null,
         "Year" : "AAAA"
      },
      {
         "Base" : "GGGG",
         "Format" : "FFFF",
         "Name" : "EEEE",
         "Title" : "DDDD",
         "Year" : "CCCC"
      }
   ]
}

관련 정보