The issue you're encountering is due to a common pitfall in Bash: the pipe creates a subshell, and variables modified inside the subshell are not visible to the parent shell.
In your code:
fzf_list=""
jq ... | while IFS='|' read -r key value; do
...
fzf_list+="$key $value"$'\n'
done
The while loop is running in a subshell because of the pipe from jq. Any changes to fzf_list inside this loop are local to the subshell and don't affect the fzf_list variable in the main shell.
To solve this, you can use one of these approaches:
- Use process substitution:
fzf_list=""
while IFS='|' read -r key value; do
echo "Processing $key.subkey1: $value"
fzf_list+="$key $value"$'\n'
done < <(jq -r '
to_entries[] |
select(.value.subkey1 != null) |
"\(.key)|\(.value.subkey1)"
' "$json_file")
echo "fzf_list: $fzf_list"
- Use an array to capture the output, then process it:
mapfile -t entries < <(jq -r '
to_entries[] |
select(.value.subkey1 != null) |
"\(.key)|\(.value.subkey1)"
' "$json_file")
fzf_list=""
for entry in "${entries[@]}"; do
IFS='|' read -r key value <<< "$entry"
echo "Processing $key.subkey1: $value"
fzf_list+="$key $value"$'\n'
done
echo "fzf_list: $fzf_list"
- Use a here-string with
readin a loop:
fzf_list=""
while IFS='|' read -r key value; do
echo "Processing $key.subkey1: $value"
fzf_list+="$key $value"$'\n'
done <<< "$(jq -r '
to_entries[] |
select(.value.subkey1 != null) |
"\(.key)|\(.value.subkey1)"
' "$json_file")"
echo "fzf_list: $fzf_list"
All of these methods avoid the subshell issue and will allow fzf_list to be updated correctly. Choose the one that best fits your scripting style and requirements.