69 lines
1.9 KiB
Bash
69 lines
1.9 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# generic JSON parser in pure bash and awk.
|
|
# reads JSON from stdin and outputs a flattened list of key-value pairs.
|
|
# example input: {"plugins": {"my_plugin": {"version": "1.0", "arr": [1, 2]}}}
|
|
# example output:
|
|
# plugins.my_plugin.version="1.0"
|
|
# plugins.my_plugin.arr[0]=1
|
|
# plugins.my_plugin.arr[1]=2
|
|
|
|
# pardon my french
|
|
parse_json() {
|
|
# Tokenize the JSON using grep
|
|
grep -oE '"([^"\\]|\\.)*"|true|false|null|[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?|[][}{:,]' | \
|
|
awk '
|
|
BEGIN {
|
|
depth=0;
|
|
key=""
|
|
}
|
|
{
|
|
token = $0
|
|
if (token == "{") {
|
|
depth++
|
|
is_key[depth] = 1
|
|
array_idx[depth] = ""
|
|
} else if (token == "}") {
|
|
delete path[depth]
|
|
delete array_idx[depth]
|
|
depth--
|
|
} else if (token == "[") {
|
|
depth++
|
|
is_key[depth] = 0
|
|
array_idx[depth] = 0
|
|
} else if (token == "]") {
|
|
delete array_idx[depth]
|
|
delete path[depth]
|
|
depth--
|
|
} else if (token == ":") {
|
|
is_key[depth] = 0
|
|
} else if (token == ",") {
|
|
if (array_idx[depth] != "") {
|
|
array_idx[depth]++
|
|
} else {
|
|
is_key[depth] = 1
|
|
}
|
|
} else {
|
|
if (is_key[depth] == 1) {
|
|
# Remove quotes from the key
|
|
gsub(/^"|"$/, "", token)
|
|
path[depth] = token
|
|
} else {
|
|
# It is a value
|
|
p = ""
|
|
for (i=1; i<=depth; i++) {
|
|
if (array_idx[i] != "") {
|
|
p = p "[" array_idx[i] "]"
|
|
} else if (path[i] != "") {
|
|
p = p "." path[i]
|
|
}
|
|
}
|
|
# Remove leading dot
|
|
sub(/^\./, "", p)
|
|
print p "=" token
|
|
}
|
|
}
|
|
}
|
|
'
|
|
}
|