On 10/16/2012 03:21 AM, DJ Mills wrote:
On Mon, Oct 15, 2012 at 8:08 PM, DJ Mills<danielmil...@gmail.com> wrote:
while read -r attr state; do
if [[ $shellopts = *:"$attr":* ]]; then
set -o "$attr"
else
set +o "$attr"
fi
done< <(set -o)
Erm, correction, that won't work for the first and last values in shellopts.
You could add colons to $shellopts ( [[ :$shellopts: = *:"$attr":* ]] ), or
use an array:
####
inarray() {
local n=$1 h
shift
for h; do
[[ $n = "$h" ]]&& return
done
return 1
}
IFS=: read -ra opts<<<"$shellopts"
while read -r attr state; do
if inarray "$attr" "${opts[@]}"; then
set -o "$attr"
else
set +o "$attr"
fi
done< <(set -o)
####
Or with bash 4, a more efficient version using an associative array:
####
declare -A setopts
IFS=: read -ra opts<<<"$shellopts"
for opt in "${opts[@]}"; do
setopts[$opt]=1
done
unset opts
while read -r attr state; do
if ((opts[$attr])); then
set -o "$attr"
else
set +o "$attr"
fi
done< <(set -o)
####
I think making an array here is a bit too much, but I like the approach with
pattern and surrounding colons - this way it's much less code and could still
be made safe. I didn't think about using here-strings with read - great trick!
And I should keep in mind -a "read" option.
I know that the shell options are known beforehand, but it's always a good idea
to use safe coding practices. These methods are safe for any values in the
"$shellopts" string, whereas yours would break for spaces or regex characters.
Yes, that unsafe approach was specifically to make code simpler, given
restricted range of input. I should've verified the argument before using it
in the for loop, probably.
You should also make sure to quote all of your expansions.
Yes, I usually do that.
Would it be an option to create the needed environment in a subshell, where you
can set whatever options you'd like and not worry about them persisting?
Yes, I do that in some cases, but I also need to disable/enable errexit before
and after some subshells to stop them from terminating the containing shell in
Bash 4 and capturing the status. Plus, some other options need temporary
disabling for some third-party function calls - using subshells every time for
that might be an overkill and then some of them do eval's.
By the way, if anyone has a more efficient way to create an associative array
like that other than that loop, I'd love to see it.
Me too :)
Thanks, Daniel.
Sincerely,
Nick