У меня есть файл csv из 100000 идентификаторов

wef7efwe1fwe8
wef7efwe1fwe3
ewefwefwfwgrwergrgr

Которые преобразуются в объект json с помощью jq

output=$(jq -Rsn '
{"id":
  [inputs
    | . / "\n"
    | (.[] | select(length > 0) | . / ";") as $input
    | $input[0]]}
' <$FILE)

Выход

{
  "id": [
         "wef7efwe1fwe8",
         "wef7efwe1fwe3",
         ....
   ]
}

В настоящее время мне нужно вручную разбить файл на более мелкие файлы размером 10000 строк ... потому что вызов API имеет ограничение.

Я хотел бы иметь способ автоматически перебирать большой файл ... и использовать только 10000 строк как $ FILE ... до конца списка.

2
chidog12 29 Авг 2020 в 20:04

2 ответа

Лучший ответ

Я бы использовал команду split и написал бы для нее небольшой сценарий оболочки:

#!/bin/bash
input_file=ids.txt
temp_dir=splits
api_limit=10000

# Make sure that there are no leftovers from previous runs
rm -rf "${temp_dir}"
# Create temporary folder for splitting the file
mkdir "${temp_dir}"
# Split the input file based on the api limit
split --lines "${api_limit}" "${input_file}" "${temp_dir}/"

# Iterate through splits and make an api call per split
for split in "${temp_dir}"/* ; do
    jq -Rsn '
        {"id":
          [inputs
            | . / "\n"
            | (.[] | select(length > 0) | . / ";") as $input
            | $input[0]]
        }' "${split}" > api_payload.json

    # now do something ...
    # curl -dapi_payload.json http://...

    rm -f api_payload.json
done

# Clean up
rm -rf "${temp_dir}"
1
hek2mgl 30 Авг 2020 в 07:20

Вот простое и эффективное решение, которое в своей основе просто использует jq. Он использует параметр командной строки -c. Я использовал xargs printf ... для иллюстрации - в основном, чтобы показать, насколько легко настроить конвейер оболочки.

< data.txt jq -Rnc '
  def batch($n; stream):
    def b: [limit($n; stream)]
    | select(length > 0)
    | (., b);
    b;

  {id: batch(10000; inputs | select(length>0) | (. / ";")[0])}
' | xargs printf "%s\n"

Параметризация размера партии

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

jq --argjson n 10000 ....

И, конечно же, использование $n вместо 10000 в программе jq.

Почему "def b:"?

Для эффективности. TCO jq (оптимизация хвостовой рекурсии) работает только для фильтров arity-0.

Обратите внимание на -s

В исходном сообщении Q параметры командной строки -sn используются вместе с inputs. Использование -s с inputs сводит на нет всю цель inputs, которая состоит в том, чтобы сделать возможным обработку ввода потоково-ориентированным способом (т.е. одна строка ввода или один объект JSON за раз).

1
peak 30 Авг 2020 в 15:39