Really short answer: Use more quotes!
local output="$(\
cat "${vim_file}" | \
sed -rne "${EXTRACT_ENTITIES}" | \
sed -re "${CLEAR_LEADING_QUOTES}" | \
sed -re "${NORMALIZE_NAMES}" \
)"
Longer answer: It's almost always a good idea to double-quote variable references and command substitutions. Double-quoting prevents them from being subject to word splitting and filename wildcard expansion, which is rarely something you want, and can cause confusing problems.
There are situations where it's safe to leave the double-quotes off, but the rules are confusing and hard to remember, and easy to get wrong. This is one of those confusing cases. One of the situations where word splitting and wildcard expansion don't happen (and therefore it's safe to leave the double-quotes off) is on the right-hand side of an assignment:
var=$othervar # safe to omit double-quotes
var2=$(somecommand) # also safe
var="$othervar" # this also works fine
var2="$(somecommand)" # so does this
Some shells extend this to assignments that're part of a command, like local
or export
:
export var=$othervar # *Maybe* ok, depending on the shell
local var2=$(somecommand) # also *maybe* ok
bash treats these as a type of assignment, so it doesn't do the split-expand thing with the values. But dash treats this more like a regular command (where the arguments do get split-expanded), so if your script is running under dash it can have problems like this.
For example, suppose somecommand
prints "export and local are shell commands." Then in dash, local var2=$(somecommand)
would expand to:
local var2=export and local are shell commands.
...which would declare the local variables var2
(which gets set to "export"), and
, local
, are
, and shell
. It would also try to declare commands.
as a local variable, but fail because it's not a legal variable name.
Therefore, use more quotes!
export var="$othervar" # Safe in all shells
local var2="$(somecommand)" # also safe
Or separate the declarations (or both!):
export var
var=$othervar # Safe in all shells, with or without quotes
local var2
var2=$(somecommand) # also safe, with or without quotes