2016-11-02 3 views
2

Предположим, у нас есть массив JSON длиной 5 и мы хотим разбить массив на несколько массивов длины 2 и сохранить сгруппированные элементы в разные файлы, используя инструменты командной строки linux ,Разделите массив JSON на несколько файлов с помощью инструментов командной строки

Я попробовал его с помощью jq и split инструментов (я доволен любой подход, который может быть выполнен из Баш скрипт):

$ echo '[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' | jq -c -M '.[]' | split -l 2 -d -a 3 - meta_ 
$ tail -n +1 meta_* 
==> meta_000 <== 
{"key1":"value1"} 
{"key2":"value2"} 

==> meta_001 <== 
{"key3":"value3"} 
{"key4":"value4"} 

==> meta_002 <== 
{"key5":"value5"} 

Предыдущая команда сохраняет элементы в файлах правильно, но мы должны преобразовать их в допустимый формат массива JSON. Я устал с --filter вариант:

$ echo '[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' | jq -c -M '.[]' | split -l 2 -d -a 3 - meta2_ --filter='jq --slurp -c -M' 
[{"key1":"value1"},{"key2":"value2"}] 
[{"key3":"value3"},{"key4":"value4"}] 
[{"key5":"value5"}] 
$ tail -n +1 meta2_* 
tail: cannot open 'meta2_*' for reading: No such file or directory 

Однако он показывает вывод на экране, но результаты не сохраняются. Я попытался переслать вывод, но я получаю сообщение об ошибке:

echo '[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' | jq -c -M '.[]' | split -l 2 -d -a 3 - meta2_ --filter='jq --slurp -c -M > $FILE' 
... 
split: with FILE=meta2_000, exit 2 from command: jq --slurp -c -M > $FILE 

Любые подсказки или лучшие подходы?

EDIT: Я попытался с двойными кавычками @andlrc предложил:

$ echo '[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' | jq -c -M '.[]' | split -l 2 -d -a 3 - meta2_ --filter="jq --slurp -c -M > $FILE" 
bash: -c: line 0: syntax error near unexpected token `newline' 
bash: -c: line 0: `jq --slurp -c -M > ' 
split: with FILE=meta2_000, exit 1 from command: jq --slurp -c -M > 
$ cat meta_000 | jq --slurp -c -M 
[{"key1":"value1"},{"key2":"value2"}] 
+0

... вы не будете принимать ответ, который не использует 'split'? (То есть: Пожалуйста, избегайте предубеждений о том, какие инструменты - лучший способ ответить на вопрос в самом вопросе). –

+0

@CharlesDuffy Я могу принять и ответить без использования split, спасибо за совет – Emer

ответ

0

Нарезка на два отдельных jq вызовов позволяет второй использовать input помощника, чтобы обрабатывать только одну часть входного сигнала на один раз. Использование вспомогательного помощника try во втором случае позволяет грациозно обрабатывать неполные строки, если у вас нет двух элементов ввода слева.


s='[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' 

jq '.[]' <<<"$s" | \ 
    jq -c -n 'repeat(input as $i1 | try (input as $i2 | [$i1, $i2]) catch [$i1])?' | \ 
    split -l 2 -d -a 3 - meta_ 

... излучает, в первом файле:

[{"key1":"value1"},{"key2":"value2"}] 
[{"key3":"value3"},{"key4":"value4"}] 

... и, во вторых:

[{"key5":"value5"}] 
0

я узнал решение, используя jq и split инструментов. Мне не хватало двойных кавычек, рисунок '.' в jq и scape $ с обратной косой чертой.

$ echo '[{"key1":"value1"},{"key2":"value2"},{"key3":"value3"},{"key4":"value4"},{"key5":"value5"}]' | 
    jq -c -M '.[]' | 
    split -l 2 -d -a 3 - meta2_ --filter="jq --slurp -c -M '.' >\$FILE" 
$ tail -n +1 meta2_* 
==> meta2_000 <== 
[{"key1":"value1"},{"key2":"value2"}] 

==> meta2_001 <== 
[{"key3":"value3"},{"key4":"value4"}] 

==> meta2_002 <== 
[{"key5":"value5"}] 
3

Будет легче собрать массивы в jq-фильтре, а затем разделить на файлы в строке. Никакой дополнительной фильтрации не требуется.

range(0; length; 2) as $i | .[$i:$i+2] 

производит:

[{"key1":"value1"},{"key2":"value2"}] 
[{"key3":"value3"},{"key4":"value4"}] 
[{"key5":"value5"}] 

Так положить все это вместе.

$ jq -cM --argjson sublen '2' 'range(0; length; $sublen) as $i | .[$i:$i+$sublen]' \ 
    input.json | split -l 1 -da 3 - meta2_