Is there a simple way to store bash variables via jq?

I am seeking an easy way to create persistent bash associative array (dictionary) storage without using declare and its options to manually read and write associative arrays externally.

‘jq’ and ‘json’ storage is certainly more capable than internal bash storage, but a simple answer for interfacing bash with ‘jq’ is eluding me in the huge mass of ‘jq’ information.

Can I use jq and JSON files to store/recall/delete persistent keyed string values in bash instead of using volatile bash associative arrays?

Note: Thank you for your comments and I believe I’ve worded my question better, but to add an example is not applicable to this question.

Asked By: Paul

||

Read

Reading a value is easy enough via --raw-output which removes js quoting in the output and // empty which removes null (and false) output…

echo '{"Z":"zee","V":"vee"}' > d
V=$(jq --raw-output '.V // empty' d)

Use --exit-status if you want to distinguish between the empty string value and not found which js calls null

echo '{"Z":"zee","V":"vee"}' > d
V=$(jq --exit-status --raw-output '.X' d)

Assigns null to $V and 1 to $? because key X was not found.

Write

Passing a value via --arg NAME VALUE causes jq to accept VALUE as a command line argument and assign it’s JSON string representation to NAME which can be referenced in the jq input as $ARGS.named.NAME

echo '{"Z":"zee","V":"vee"}' > d
V=$'Thistis a fancynvalue containing "quotes" and more \'
sponge d < <(jq --arg V "$V" '."V"=$ARGS.named.V' d)

Passing a value via --rawfile NAME FILE causes jq to accept the contents of FILE and assign it’s JSON string representation to NAME which can be referenced in the jq input as $NAME

echo '{"Z":"zee","V":"vee"}' > d
sponge d < <(jq --rawfile V <(printf 'Thistis a fancynvalue containing "quotes" and more \') '."V"=$V' d)

Delete

Deleting a value is easy…

sponge d < <(jq 'del(.V)' d)

Comment

Examples here use the form sponge FILE < <(jq ... FILE) to emulate an inline replace of FILE. Any other method like JSON=$(jq ...) can be used, but jq ... FILE | sponge FILE causes sponge to empty FILE if an error occurs during jq (easily caused by malformed input or literal) which cannot be stopped by set -e and set -o pipefail. On the bright side, sponge FILE < <(jq ... FILE) halts execution of sponge if an error occurs during generation of its input leaving FILE intact.

Answered By: Paul
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.