Skip to content

Instantly share code, notes, and snippets.

@mohd-akram
Last active July 5, 2025 05:25
Show Gist options
  • Save mohd-akram/1c0d4cb337b62e3cce0ab7e02e6281fd to your computer and use it in GitHub Desktop.
Save mohd-akram/1c0d4cb337b62e3cce0ab7e02e6281fd to your computer and use it in GitHub Desktop.
Extract a value from a JSON object or array in awk
#
# 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