Last active
July 5, 2025 05:25
-
-
Save mohd-akram/1c0d4cb337b62e3cce0ab7e02e6281fd to your computer and use it in GitHub Desktop.
Extract a value from a JSON object or array in awk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Extract a JSON value in an object or array: | |
# | |
# name = decode_json_string(get_json_value(json, "author.name")) | |
# date = decode_json_string(get_json_value(json, "events.0.date")) | |
# | |
# Or an entire object: | |
# | |
# get_json_value(json, "dependencies", deps) | |
# | |
# for (name in deps) | |
# version = decode_json_string(deps[name]) | |
# | |
# Or array: | |
# | |
# get_json_value(json, "payload.tree.items", items) | |
# | |
# for (i = 0; items[i]; i++) { | |
# get_json_value(items[i], null, item) | |
# type = decode_json_string(item["type"]) | |
# name = decode_json_string(item["name"]) | |
# } | |
# | |
function get_json_value( \ | |
s, key, a, | |
skip, type, all, rest, isval, i, c, k, null \ | |
) { | |
if (match(s, /^[[:space:]]+/)) s = substr(s, RLENGTH+1) | |
type = substr(s, 1, 1) | |
all = key == "" && key == 0 | |
if (type != "{" && type != "[") { | |
if (!all) error("invalid json array/object " s) | |
if (!match(s, /^(null|true|false|"(\\.|[^\\"])*"|[.0-9Ee+-]+)/)) | |
error("invalid json value " s) | |
return substr(s, 1, RLENGTH) | |
} | |
if (!all && (i = index(key, "."))) { | |
rest = substr(key, i+1) | |
key = substr(key, 1, i-1) | |
} | |
if ((isval = type == "[")) k = 0 | |
for (i = 2; i <= length(s); i += length(c)) { | |
if (match(substr(s, i), /^[[:space:]]+/)) { | |
c = substr(s, i, RLENGTH) | |
continue | |
} | |
c = substr(s, i, 1) | |
if (c == "}" || c == "]") break | |
else if (c == ",") { if ((isval = type == "[")) ++k } | |
else if (c == ":") isval = 1 | |
else { | |
if (!all && k == key && isval) | |
return get_json_value(substr(s, i), rest, a) | |
c = get_json_value(substr(s, i), null, null, 1) | |
if (all && !skip && isval) a[k] = c | |
if (c ~ /^"/ && !isval) k = substr(c, 2, length(c)-2) | |
} | |
} | |
if ((type == "{" && c != "}") || (type == "[" && c != "]")) | |
error("unterminated json array/object " s) | |
if (all) return substr(s, 1, i) | |
} | |
function decode_json_string(s, out, esc) { | |
if (s !~ /^"./ || substr(s, length(s), 1) != "\"") | |
error("invalid json string " s) | |
s = substr(s, 2, length(s)-2) | |
esc["b"] = "\b"; esc["f"] = "\f"; esc["n"] = "\n"; esc["\""] = "\"" | |
esc["r"] = "\r"; esc["t"] = "\t"; esc["/"] = "/" ; esc["\\"] = "\\" | |
while (match(s, /\\/)) { | |
if (!(substr(s, RSTART+1, 1) in esc)) | |
error("unknown json escape " substr(s, RSTART, 2)) | |
out = out substr(s, 1, RSTART-1) esc[substr(s, RSTART+1, 1)] | |
s = substr(s, RSTART+2) | |
} | |
return out s | |
} | |
function error(msg) { | |
printf "%s: %s\n", ARGV[0], msg > "/dev/stderr" | |
exit 1 | |
} | |
# | |
# Example usage | |
# | |
# $ curl https://httpbin.org/json | awk -f json.awk slideshow.title | |
# "Sample Slide Show" | |
# | |
BEGIN { | |
while (ret = getline l < "/dev/stdin") { | |
if (ret == -1) error("getline error") | |
s = s l "\n" | |
} | |
print get_json_value(s, ARGV[1]) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment