NickName:coffeeak Ask DateTime:2016-11-21T22:41:00 How to use jq to convert this string to JSON? How can I use jq to convert the following lines to a JSON format? payment_test_service1_api[host] HOST1 payment_test_service1_api[username] USERNAME1 payment_test_service1_api[password] PASSWORD1 To this JSON format: "payment_test" { "service1" : { "api": { "host": "HOST1", "username": "USERNAME1", "password": "PASSWORD1" } } } Copyright Notice:Content Author:「coffeeak」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.Link to original article:https://stackoverflow.com/questions/40722754/how-to-use-jq-to-convert-this-string-to-json Answers peak 2016-11-21T15:52:59 The following is more general than @chepner's solution (it uses add and therefore is not restricted to three key-value pairs) and perhaps slightly simpler:\n\n$ jq -Rn 'inputs | match(\"\\\\[(.*)\\\\] (.*)\")\n | .captures | {(.[0].string): (.[1].string)} ' tmp.txt |\n jq -s '{payment_test: { service1: { api: add }}} '\n\n\nNow it's easy to see how to eliminate the second call to jq:\n\njq -Rn '[ inputs | match(\"\\\\[(.*)\\\\] (.*)\")\n | .captures | {(.[0].string): (.[1].string)}]\n | {payment_test: { service1: { api: add }}} ' tmp.txt\n\n\nUsing named capture variables\n\nAn improvement would be to use named capture variables. jq provides a filter, capture, for creating an object from the capture variables; it can be used in conjunction with from_entries like so:\n\n[inputs | capture(\"\\\\[(?<key>.*)\\\\] (?<value>.*)\")]\n| from_entries\n| {payment_test: { service1: { api: . }}} \n\n\nUsing such techniques, the string \"payment_test_service1_api\" could also be parsed, but the OP expectations regarding this are unclear, so maybe that's best left for another Q&A.", chepner 2016-11-21T15:12:16 Update: see @peak's answer for the generalization I couldn't quite get to.\n\n\n\nThis is far from the best solution, but demonstrates that it is possible to generate some JSON from arbitrary text.\n\njq -Rrn 'inputs | match(\"\\\\[(.*)\\\\] (.*)\") | .captures[]|.string ' tmp.txt |\n jq -Rn '{\n payment_test: {\n service1: {\n api: {\n \"\\(input)\": input,\n \"\\(input)\": input,\n \"\\(input)\": input\n }\n }\n }\n }\n'\n\n\nHere's a breakdown of each command: \n\n\nThe first one reads the input as raw text (-R), line-by-line inside the filter (-n along with the inputs function), and outputs raw text (-r) corresponding to the text in brackets and the rest of the line following the brackets.\n\nIt is instructive to run the first command on your input one filter at a time to see how the full filter works. (That is, run each of the following in order:\n\n\njq -Rrn 'inputs' tmp.txt\njq -Rrn 'inputs | match(...)' tmp.txt\njq -Rrn 'inputs | match(...) | .captures' tmp.txt\njq -Rrn 'inputs | match(...) | .captures[] | .string' tmp.txt\n\n\n)\nThe second command simply reads each line, again as raw text and explicitly using input, and builds the desired object from each piece.\n\n\nIt should be possible to combine this into one call to jq; my skills at more complex commands are limited, but this demonstrates that you can cobble together a solution using simple pieces.",