Last active
June 8, 2024 03:50
-
-
Save donaldguy/a56b9dc19a48bd7e7b86de3e0052f6c8 to your computer and use it in GitHub Desktop.
Have you ever had a json object or array and wished it was a serious of zsh/bash variables? … yeah ¬_¬ , totally, me neither 😅 https://jqplay.org/s/biOH4MLXDfe
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
def declare: ( | |
.t as $type | .var as $var | | |
{"array": "-a", "object": "-A"}[$type] as $arg | | |
"declare \($arg) \($var);" | |
); | |
def shellify: ( | |
. as $container | | |
$container.value | keys | .[] | ( . as $k | | |
($container.value | .[$k]) as $item | | |
($item | type) as $item_type | | |
(if $container.type == "array" then | |
[ | |
($container.var | rtrimstr("S") | rtrimstr("s")), | |
(($item["id"]? // $k) | tostring| gsub("[^A-Za-z0-9_]"; "_")) | |
] | |
else | |
[$container.var, ($k | tostring| gsub("[^A-Za-z0-9_]"; "_"))] | |
end) | .[0] as $var_prefix | .[1] as $var_suffix | | |
if ($item_type == "array" or $item_type == "object") then | |
(["p", $var_prefix, $var_suffix] | join("_")) as $item_var | | |
({t: $item_type, var: $item_var} | declare ) as $decl | | |
(if $container.type == "array" then | |
$k | . + 1 | |
else | |
# in bash > 4, and zsh > 6.9 (unreleased) you could probs `declare -n` and use that? | |
"\($k)_P" | |
end) as $item_pointer_index | | |
([ | |
$decl, | |
({var: $item_var, value: $item, type: $item_type} | | |
shellify ), | |
([$container.var, "[", $item_pointer_index, "]=\"", $item_var, "\";"] | join("")) | |
] | join("\n")) | |
else | |
$k | ((numbers | . + 1) // .) as $item_key | | |
$item | ((numbers | floor) // . | @sh ) as $item_value | | |
[$container.var, "[", $item_key, "]=", $item_value, ";"] | join("") | |
end) | |
); | |
type as $type | | |
[ ({t: $type, var: $k } | declare), | |
({ | |
var: $k, | |
value: ., | |
type: $type, | |
} | shellify )] | join("\n") |
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
function autoshell_json() { | |
local k=${1:-VALUE} | |
jq -r --arg k $k "$(cat shell_vars_from_json.jq)" | |
} | |
#e.g. | |
eval "$(curl "https://api.github.com/gists/a56b9dc19a48bd7e7b86de3e0052f6c8" | autoshell_json GIST)" | |
#whereafter | |
# $ typeset -p 1 GIST | |
# typeset -A GIST=( | |
# [comments]=2 | |
# [comments_url]=https://api.github.com/gists/a56b9dc19a48bd7e7b86de3e0052f6c8/comments | |
# [commits_url]=https://api.github.com/gists/a56b9dc19a48bd7e7b86de3e0052f6c8/commits | |
# [created_at]=2024-06-07T18:36:54Z | |
# [description]='Have you ever had a json object or array and wished it was a serious of zsh/bash variables? … yeah ¬_¬ , totally, me neither 😅 https://jqplay.org/s/cGKAsD8mLdU' | |
# [files_P]=p_GIST_files | |
# [forks_P]=p_GIST_forks | |
# [forks_url]=https://api.github.com/gists/a56b9dc19a48bd7e7b86de3e0052f6c8/forks | |
# [git_pull_url]=https://gist.github.com/a56b9dc19a48bd7e7b86de3e0052f6c8.git | |
# [git_push_url]=https://gist.github.com/a56b9dc19a48bd7e7b86de3e0052f6c8.git | |
# [history_P]=p_GIST_history | |
# [html_url]=https://gist.github.com/donaldguy/a56b9dc19a48bd7e7b86de3e0052f6c8 | |
# [id]=a56b9dc19a48bd7e7b86de3e0052f6c8 | |
# [node_id]=G_kwDNqIDaACBhNTZiOWRjMTlhNDhiZDdlN2I4NmRlM2UwMDUyZjZjOA | |
# [owner_P]=p_GIST_owner | |
# [public]=true | |
# [truncated]=false | |
# [updated_at]=2024-06-07T20:41:05Z | |
# [url]=https://api.github.com/gists/a56b9dc19a48bd7e7b86de3e0052f6c8 | |
# [user]=null | |
# ) | |
# $ typeset p_GIST_files | |
# p_GIST_files=( [shell_vars_from_json.jq_P]=p_p_GIST_files_shell_vars_from_json_jq [usage.zsh_P]=p_p_GIST_files_usage_zsh ) | |
echo "${(P)GIST[history_P]}" | |
# p_p_GIST_history_0 p_p_GIST_history_1 p_p_GIST_history_2 p_p_GIST_history_3 p_p_GIST_history_4 p_p_GIST_history_5 p_p_GIST_history_6 p_p_GIST_history_7 | |
echo ${(P)GIST[history_P][1]} | |
# p_p_GIST_history_0 | |
for p in ${(@P)GIST[history_P]}; do echo ${${(P)p}[committed_at]}; done | |
# 2024-06-07T20:23:56Z | |
# 2024-06-07T20:23:31Z | |
# 2024-06-07T19:19:39Z | |
# 2024-06-07T18:47:21Z | |
# 2024-06-07T18:44:44Z | |
# 2024-06-07T18:39:03Z | |
# 2024-06-07T18:37:34Z | |
# 2024-06-07T18:36:54Z | |
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
autoshell_json_stream() { | |
jq --join-output --arg prefix ${1:-INPUT} --stream ' | |
1 as $true | 0 as $false | "$NULL" as $null | | |
[.[0], .[1:]] as [$path, $maybe_val] | |
| reduce ($path[0:-1][]) as $p ( | |
{acc: [$prefix], collection: [[$prefix]]}; | |
(.acc + [($p | tostring | gsub("[^A-Za-z0-9]"; "00"))]) as $new | | |
{acc: $new, collection: (.collection + [$new])}) | |
| (.collection | map(join("_")) ) as $varcs | |
| | |
reduce range($varcs | length) as $i ([]; . + [ | |
"declare -\( | |
$path[$i] | ((numbers | "a") // (strings | "A")) | |
) \($varcs[$i]);\n"] ) | |
+( | |
if ($maybe_val | length) == 1 then ($maybe_val as [$val] | | |
$val | [ | |
($varcs| last), | |
"[", ($path|last| ((numbers | . + 1) // .) ), "]=", | |
((strings | @sh) // | |
(numbers | "\"$(( \(tostring) ))\"") // | |
(booleans | if . then $true else $false end) // | |
(nulls | $null) | |
), ";\n" | |
]) else | |
$varcs | last | | |
["test -n \"${ZSH_VERSION}\" && whence _json_autoshell_end_of_var &> /dev/null && _json_autoshell_end_of_var \(.)\n"] | |
end) | join("")' | |
} | |
_json_autoshell_end_of_var() { | |
local parent_v=$1 | |
local parent_v_type=${$(typeset +m $parent_v)#$parent_v} | |
local turn_glob_back_off=$(setopt | grep -q extendedglob && echo "no") | |
setopt extendedglob | |
local -a child_vars=($(typeset +m "${parent_v}_[^_]#")) | |
while [[ ${#child_vars} > 0 ]]; do | |
local var_name=$child_vars[2] | |
local var_type=$child_vars[1] | |
shift 2 child_vars | |
case $parent_v_type in | |
array*) | |
eval "${parent_v}+=($var_name)" ;; | |
association*) | |
local var_suffix=${var_name#${parent_v}_} | |
case $var_type in | |
array) | |
eval "${parent_v}[.${var_suffix}@]=${var_name}" ;; | |
association) | |
eval "${parent_v}[.${var_suffix}]=${var_name}" ;; | |
esac | |
esac | |
done | |
if [[ "${turn_glob_back_off:-yes}" != "no" ]]; then unsetopt extendedglob; fi | |
} |
That this is the case kinda makes me understand why zstyle
is a thing ... but only kinda
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Individual nested access is kinda terrible:
As comment mentions I think
nameref
s might make this less bad in modern bash and forthcoming zsh, but I'm not sure