преобразование строк в json в bash

Я хотел бы преобразовать список в массив JSON. Я смотрю на jq для этого, но примеры в основном касаются разбора JSON (не создавая его). Было бы неплохо знать, что произойдет правильный побег. Мой список - это однострочные элементы, поэтому новая строка, вероятно, будет лучшим разделителем.

5 ответов


Я также пытался преобразовать кучу строк в массив JSON и был в тупике, пока не понял, что -s был единственным способом, которым я мог обрабатывать более одной строки за раз в jq выражение, даже если это означало, что мне придется парсить строку вручную.

jq -R -s -c 'split("\n")' < just_lines.txt
  • -R для чтения raw input
  • -s читать все входные данные как одну строку
  • -c чтобы не очень печатать вывод

легко peasy.

Edit: я на jq ≥ 1.4, что, по-видимому, когда split встроенный был введен.


вы также можете использовать jq -R . форматировать каждую строку как строку JSON, а затем jq -s (--slurp) чтобы создать массив для входных строк после их разбора как JSON:

$ printf %s\n aa bb|jq -R .|jq -s .
[
  "aa",
  "bb"
]

метод в ответе chbrown добавляет пустой элемент в конец, если вход заканчивается лентой, но вы можете использовать printf %s "$(cat)" чтобы удалить конечные linefeeds:

$ printf %s\n aa bb|jq -R -s 'split("\n")'
[
  "aa",
  "bb",
  ""
]
$ printf %s\n aa bb|printf %s "$(cat)"|jq -R -s 'split("\n")'
[
  "aa",
  "bb"
]

если входные строки не содержат символов управления ASCII (которые должны быть экранированы в строках в допустимом JSON), вы можете использовать sed:

$ printf %s\n aa bb|sed 's/["\]/\&/g;s/.*/"&"/;1s/^/[/;$s/$/]/;$!s/$/,/'
["aa",
"bb"]

--raw-input, затем --slurp

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

cat /etc/hosts  | jq  --raw-input .  | jq --slurp .

вернет вас:

[
  "fe00::0 ip6-localnet",
  "ff00::0 ip6-mcastprefix",
  "ff02::1 ip6-allnodes",
  "ff02::2 ip6-allrouters"
]

объяснение

 --raw-input/-R:

       Don´t parse the input as JSON. Instead, each line of text is passed
       to  the  filter  as  a  string.  If combined with --slurp, then the
       entire input is passed to the filter as a single long string.

 --slurp/-s:

       Instead of running the filter for each JSON object  in  the  input,
       read  the entire input stream into a large array and run the filter
       just once.

Я нашел в man-странице для jq и через эксперименты то, что мне кажется более простым ответом.

$ cat test_file.txt | jq -Rsc '. / "\n" - [""]'
["aa","bb"]

- R читать, не пытаясь разобрать json,- s говорит, чтобы прочитать все входные данные как одну строку, а-c для однострочного вывода-не обязательно, но это то, что я искал.

затем в строке я передаю jq,'. говорит Возьми ввод, как это. '/\N ' говорит разделить строку (разделить ее) на новые строки. '- [""] 'Говорит, чтобы удалить из результирующего массива любые пустые строки (в результате дополнительной новой строки в конце).

Это одна строка и без каких-либо сложных конструкций, используя только простые встроенные функции jq.


обновление: если ваш jq имеет inputs вы можете просто написать:

jq -R [inputs] /etc/hosts 

для создания массива строк JSON.