Связать элементы в табличной форме из файла Json с jq - PullRequest
2 голосов
/ 31 мая 2019

Я новичок в jq, и у меня есть следующий код для получения табличных значений для каждого элемента с именем Abc:

["Abc"], ( .. | objects | select(has("Abc")) | [.["Abc"]] ) | @tsv

Это текущий вывод, который я получаю:

"Abc"
"4"
"2"
"1"
"9"
"3"
"2"
"4"
"9"

Я хотел бы добавить 4 столбца слева, чтобы показать для каждого значения Abc соответствующую страницу, строку и столбец. Дополнительно, если возможно, в качестве первого столбца добавьте счетчик от 1 до количества элементов «Abc».

Ниже я показываю текущий вывод по сравнению с желаемым выводом и структурой файла Json, чтобы уточнить: enter image description here

Входной файл Json ниже:

{
  "document": {
    "page": [
      {
        "@index": "0",
        "image": {
          "Abc": "4"
        }
      },
      {
        "@index": "1",
        "row": [
          {
            "column": [
              {
                "text": {
                  "Abc": "2"
                }
              }
            ]
          },
          {
            "column": [
              {
                "text": {
                  "Abc": "1"
                }
              },
              {
                "text": {
                  "Abc": "9"
                }
              }
            ]
          },
          {
            "column": [
              {
                "text": {
                  "Abc": "3"
                }
              }
            ]
          }
        ]
      },
      {
        "@index": "2",
        "row": [
          {
            "column": [
              {
                "text": {
                  "Abc": "2"
                }
              }
            ]
          },
          {
            "column": [
              {
                "text": {
                  "Abc": "4"
                }
              },
              {
                "text": {
                  "Abc": "9"
                }
              }
            ]
          }
        ]
      }
    ]
  }
}

Надеюсь, кто-нибудь сможет мне помочь. Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 31 мая 2019

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

Для ясности начнем с определения функции, которая добавляет номера строк:

# add a sequential id, starting at 1
def tsvRows(s):
  foreach s as $s (0; .+1; [.] + $s)
  | @tsv;

(["counter", "page", "row", "column", "Abc"] | @tsv),
tsvRows(paths as $p
  | select($p[-1] == "Abc")
  | getpath($p) as $v
  | $p
  | .[2] as $page
  | (if .[3] == "row" then .[4] else null end) as $row
  | (if .[5] == "column" then .[6] else null end) as $column
  | [$page, $row, $column, $v] )
1 голос
/ 31 мая 2019

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

["counter", "page", "row", "column", "Abc"],
(foreach (.document.page[] | objects) as $page ({page: -1, counter: 0};
  .page += 1
  | if ($page | (has("image") and (.image|has("Abc"))))
    then
      .counter +=1
      | .out = [.counter, .page, null, null, ($page|.image.Abc)]
    else foreach ($page | .row[]?) as $row (.row=-1;
      .row += 1
      | foreach ($row | .column[]) as $column (.column=-1;
          .column +=1
          | foreach ($column | .text | objects) as $x (.;
              .counter += 1
              | .out = [.counter, .page, .row, .column, $x["Abc"]]
              ; . )
           ; . )
      ; . )
    end
    ; .out )
)
| @tsv

Вывод

В частности, с параметром командной строки -rрезультат, полученный из данного ввода, следующий (включая вкладки):

counter page    row column  Abc
1   0           4
2   1   0   0   2
3   1   1   0   1
4   1   1   1   9
5   1   2   0   3
6   2   0   0   2
7   2   1   0   4
8   2   1   1   9
0 голосов
/ 31 мая 2019

, хотя вопрос был для jq, для тех, кто интересуется альтернативными решениями, вот один из них, основанный на утилите unix с обходом пути jtc:

bash $ <file.json jtc -w' ' -T0 -w'[0][page][0]<p>k<Abc>l' -T'"{p}\t\t\t{}"' -w'[0][page][1:]<p>k[row][:]<r>k[column][:]<c>k<Abc>l' -T'"{p}\t{r}\t{c}\t{}"' -j | jtc -qqw' ' -T'"#\tpage\trow\tcolumn\tAbc"' -w'[1:]<#>k<v>v' -T'"{#}\t{v}"'
#       page    row     column  Abc
1       0                       4
2       1       0       0       2
3       1       1       0       1
4       1       1       1       9
5       1       2       0       3
6       2       0       0       2
7       2       1       0       4
8       2       1       1       9
bash $ 

при первом вызове jtc первый фиктивный обходной путь (-w' ') необходим только для смещения начального индекса на 1 (в противном случае столбец # будет отображаться, начиная с idx 0)

вторая прогулка обрабатывает только первую страницу (0),

третий путь обработки обрабатывает остальную часть JSON.

PS> Раскрытие информации: я создатель jtc - оболочки cli для операций JSON

...