bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Command substitution and errexit


From: Nikolai Kondrashov
Subject: Re: Command substitution and errexit
Date: Tue, 16 Oct 2012 10:51:21 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.7) Gecko/20120922 Icedove/10.0.7

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]