A POSIX shell has a single array: the positional parameters ($1
, $2
, …), collectively accessed as "$@"
, and set with the set --
builtin. More precisely, there is one array per function instance on the current call stack, but only the array of positional parameters of the currrent function (or of the script, if outside any function) is accessible at any point. Thus, if you want to make use of this array but not clobber the parameters of the script, work in a function.
As sml has already remarked, your specific use case with grep is more simply solved by using the -F
option of grep to make it read one pattern per file line. But here's how you can solve the same problem for a command that doesn't have anything like grep -F
.
set -- -a -b
while IFS= read -r line; do
set -- -e "$line"
done < "$dictionary"
mycommand "$@" more stuff
This calls mycommand -a -b line1 line2 … more stuff
.
If you need to manipulate several lists of file names (or other strings with arbitrary contents), you can do it with judicious use eval
and very careful quoting. Getting the quoting hard is tricky. The following function takes two argument: a variable name and a string; it appends a quoted form of the string to the variable. The quoted form is a single-quoted literal, with single quotes suitably escaped, and is suitable for shell parsing.
append_to_quoted_list () {
set -- "$1" "$(printf %s. "$2" | sed "s/'/'\\\\''/")"
eval "$1=\"\${$1} '${2%?}'\""
}
Here's an example usage, to build two lists at the same time. It calls $command1
with the lines passed as arguments to -e
options, then $command2
with the lines passed as --foo=…
options.
list1= list2=
append_to_quoted_list list1 "$command1"
append_to_quoted_list list1 "$command2"
while IFS= read -r line; do
append_to_quoted_list list1 -e
append_to_quoted_list list1 "$line"
append_to_quoted_list list2 "--foo=$line"
done < "$dictionary"
eval "$list1; $list2"