Different behavior between bash shell and bash script for cmd

So I'm trying to pass certain json elements as env vars and use them later on in a script.

Sample json:

JSON='{  
    "Element1": "file-123456",
    "Element2": "Name, of, company written in, a very weird way",
    "Element3": "path/to/some/file.txt",
}'

(part of the) script:

for s in $(echo $JSON | jq "{Element1,Element2,Element3} | to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]");do
export $s
done

The problem I'm having is that Element2 is breaking the line when exporting but if I just run "echo $JSON | jq "{Element1,Element2,Element3} | to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]"" at the cmd line, it looks fine:

"Element1=file-123456"
    "Element2=Name, of, company written in, a very weird way"
    "Element3=path/to/some/file.txt"

Actual output of script:

1.bash: line 100: export: `of,': not a valid identifier
1.bash: line 100: export: `company,': not a valid identifier
1.bash: line 100: export: `written,': not a valid identifier

As can be seen, the export command inserts single quotes into the "Element2" and I'm not sure where they come from.

The second variable (Element2) only contains the first element in the string (Name,). The behavior makes sense since the line is broken but for the life in me I cannot understand how or why the export command inserts them.

Any insight is appreciated, thank you!

I don't have jq , to_entries , or any utility starting with map installed on my system so I can't reproduce your output. Nonetheless, the diagnostic output you showed us seems to have a couple of commas that don't match what was in the code you showed us.

If I was guessing at what might be wrong, the first thing I would try would be to run your script with the shell's -x and -v options enabled to get a trace of what it is doing. The second thing I would do would be to change the line in your script that is currently:

export $s

into:

export "$s"

so the export command is invoked with one operand instead of nine operands for the Element2 case when <space>s are included in the value you want to assign to that exported variable.

Not pretty, and I've invoked jq twice:

$ paste -d= <(<<<"$JSON" jq 'keys | .[]') <(<<<"$JSON" jq .[])
"Element1"="file-123456"
"Element2"="Name, of, company written in, a very weird way"
"Element3"="path/to/some/file.txt"

I imagine this will be safe in an eval:

eval $(paste -d= <(<<<"$JSON" jq 'keys | .[]') <(<<<"$JSON" jq .[]))

Andrew

====
Just checked - couldn't use it in an eval.

What I ended up doing was using a piece of code I found on stackoverflow:

json2keyvalue() {
   echo $JSON | jq -r '{Element1,Element2,Element3} | to_entries|map("\(.key)=\(.value|tostring)")[]'
}

while IFS='=' read -r key value
do
    export "$key"="$value"
done < <(json2keyvalue)
1 Like

Variables in command arguments should be in "quotes":

echo "$JSON" | jq ...

Not only that it escapes the shell expansions, it also retains the multi-line structure.
(Unless you NEED everything in one long line.)

2 Likes

I actually had it in quotes but copy pasted the initial code that I ended up adjusting.