On 10/16/2012 03:21 AM, DJ Mills wrote:
On Mon, Oct 15, 2012 at 8:08 PM, DJ Mills<[email protected]> 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
