0

I need to create a bunch of strings using heredocs which I want to store in an array so that I can run them all through processes later. For example

IFS='' read -r -d '' data  << END
{
"my": "first doc"
}
END

IFS='' read -r -d '' data  << END
{
"my": "second doc"
}
END

I know I could append to an array of docs using a construction like

docs+=("${data}")

after each heredoc, but is there a slick way I can do it directly in the read command without assigning index values (so I can change the order, add others in the middle, etc without it being awkward)?

3
  • If you're trying to process JSON, you should use jq rather than bash arrays. Commented Feb 19, 2022 at 0:42
  • BTW, note that because your heredocs don't end in NULs but read -d '' reads up to the next NUL, your read commands have nonzero exit status, so if this code were run with set -e (which is bad practice anyhow) it would fail upon reaching them. Commented Feb 19, 2022 at 0:48
  • I'm a huge jq fan, but the docs are created in a way that would be awkward with jq. Commented Feb 19, 2022 at 0:50

1 Answer 1

1

The easy approach is to build a function that uses namevars to refer to your destination array indirectly.

Note that namevars are a feature added in bash 4.3; before that release, it's not as easy to have the variable be parameterized without getting into unpleasantries like eval, so you might end up just hardcoding data as your destination if you want portability (and that makes sense in the context at hand).

append_to_array() {
  declare -n _dest="$1"
  _dest+=( "$(</dev/stdin)" )
}

append_to_array data <<'END'
{
"my": "first doc"
}
END

append_to_array data <<'END'
{
"my": "second doc"
}
END

See this running at https://ideone.com/9zEMWs

Sign up to request clarification or add additional context in comments.

2 Comments

BTW, note the use of <<'END' instead of <<END -- quoting the heredoc sigil prevents contents of that heredoc from being treated as shell syntax, should there be content able to be parsed as command substitutions / variable expansions / etc. It's thus preferable whenever there isn't a specific need for such expansions.
It turns out I could get away with function alone without the namevar (e.g.append_to_array() { myarray+=( "$(</dev/stdin)" )} for my use. However, learning about namevars as well as the quoting to avoid expansion was very helpful

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.