LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   LQ Articles Discussion (https://www.linuxquestions.org/questions/lq-articles-discussion-68/)
-   -   Minimize the amount of code in your bash scripts (https://www.linuxquestions.org/questions/lq-articles-discussion-68/minimize-the-amount-of-code-in-your-bash-scripts-4175589895/)

louigi600 09-21-2016 03:48 PM

Minimize the amount of code in your bash scripts
 
A new article entry has been added:

Minimize the amount of code in your bash scripts

Quote:

I use bash scripts to do all sorts of things, both in my spare time and for my job, and many of them require creating and reading a configuration file or parsing some options or both.
I used to end up writing very similar code over and over again and dealing with creating config files, parsing options and usage message used to take up a big part in the script. I wanted to do something about this to make my life simpler and minimize the amount of code I'd need to write for dealing with such issues and possibly stop rewriting each time nearly the same thing.

pan64 09-22-2016 04:28 AM

I'm sorry, but I need to say the code you presented is inefficient. You need to eliminate $( .. ), because that will invoke a new shell and usually can be solved without that (which will need less resources, run faster...)

louigi600 09-22-2016 04:47 AM

Yes surely but the article is on minimizing code not making it more efficient. It's focus is on reducing the amount of code necessary to deal with input flags/parameters and configuration file creation.
I'll see if I can review the code so that it's not a bad example of bash coding ... can I edit my article ?

Help me find the contents of a variable whose name is in another variable ... I know what I did is a mess but I still can't think of an alternative.

pan64 09-22-2016 06:09 AM

Quote:

Help me find the contents of a variable whose name is in another variable
Code:

A=B
B=12
echo ${A}
echo ${!A}


louigi600 09-22-2016 07:02 AM

Quote:

Originally Posted by pan64 (Post 5608605)
Code:

A=B
B=12
echo ${A}
echo ${!A}


Yes I guess I should have read better the bash man page ... No how do I edit the article to make it better ?

pan64 09-22-2016 07:06 AM

probably there is an edit button, but actually you can post an improved version too.

louigi600 09-22-2016 07:13 AM

Quote:

Originally Posted by pan64 (Post 5608623)
probably there is an edit button, but actually you can post an improved version too.

For posts there is but I can't find it for article, I wanted to avoid rewriting it just make the current version better.
But if it's not possible I guess a rewrite will be scheduled.

louigi600 09-22-2016 09:42 AM

Quote:

Originally Posted by pan64 (Post 5608579)
You need to eliminate $( .. ), because that will invoke a new shell ...

No $(command) and/or `command` is command substitution and does not invoke a shell unless the command is a shell.
It's the plain ( list ) that invokes a subshell to run the list.

Ok but still you have a point: there are some places where I can do without command substitution and I can declare som variables as integer and do without some of the ((expression)). It will be an exercise for me to write cleaner bash scripts ;)

MadeInGermany 05-05-2017 03:59 PM

The $( ) or ( ) is a sub shell.
That is another process, or at least it behaves like one.
An example should demonstrate this
Code:

x=1
echo $(x="2 $x"; echo "$x")
echo "$x"
( x="2 $x"; echo "$x" )
echo "$x"

Nothing is returned to the main shell.
My attempt for an efficient coding
Code:

get_myoptions_value ()
{ I=0
  #SEARCH_OPTION=$(echo "$1" |tr -d "-")
  SEARCH_OPTION=${1//-/}

  while [ $I -lt ${#MYOPTIONS[*]} ]
  do
    #OPTION=$(echo "${MYOPTIONS[$I]}" |cut -d "," -f 1)
    OPTION=${MYOPTIONS[$I]%%,*}" # the first comma-separated value

    #VALUE=$(echo "${MYOPTIONS[$I]}" |cut -d "," -f 4)
    VALUE=${MYOPTIONS[$I]##*,} # the last one (this might not be 4)
    #[ "$OPTION" = "$SEARCH_OPTION" ] && (echo $VALUE ; break)
    [ "$OPTION" = "$SEARCH_OPTION" ] && { echo $VALUE ; break ; }
    #I=$(expr $I + 1)
    (( I++ ))
  done
}

The { ;} is efficient because it stays in the current shell, just like a simple if-then-else.
BTW nothing speaks against
Code:

    if [ "$OPTION" = "$SEARCH_OPTION" ] ; then echo $VALUE ; break ; fi

louigi600 05-07-2017 04:22 AM

To my understanding, which may be wrong, $(command) forks the command so if it's a shell it will run a subshell if it's an executable it will execute the command obviously in another process in any case.
$(command) and `command` do the same thing I just prefer the newer $(command) syntax.
As I said before this not about optimizing code for performance but all about minimizing the amount of code necessary to deal with scripts with several options and configuration parameters.
Although I appreciate comments regarding attempting to get petter performance I do thing that they're missing the whole point of the article.

In any case a reedit or improved version is pending

MYOPTIONS is an associative array you don't need to walk the whole looking for the looking for the right element.
Code:

get_myoptions_value ()
{ I=0
  #SEARCH_OPTION=$(echo "$1" |tr -d "-")
  SEARCH_OPTION=${1//-/}

  while [ $I -lt ${#MYOPTIONS[*]} ]
  do
    #OPTION=$(echo "${MYOPTIONS[$I]}" |cut -d "," -f 1)
    OPTION=${MYOPTIONS[$I]%%,*}" # the first comma-separated value

    #VALUE=$(echo "${MYOPTIONS[$I]}" |cut -d "," -f 4)
    VALUE=${MYOPTIONS[$I]##*,} # the last one (this might not be 4)
    #[ "$OPTION" = "$SEARCH_OPTION" ] && (echo $VALUE ; break)
    [ "$OPTION" = "$SEARCH_OPTION" ] && { echo $VALUE ; break ; }
    #I=$(expr $I + 1)
    (( I++ ))
  done
}

That's not more efficient it's doing a ueless array walk and it's less readable, but yes instead of forking cut I could have removed the longest matching prefix ... that might go in the revised version.

pan64 05-07-2017 04:31 AM

for example:
Code:

eval $(echo dialog --title \"$TITLE\" --yesno  \" ${STRING[*]}\" 0 0 ) && return 1 || return 0
# can be simplified by:
dialog --title "$TITLE" --yesno  " ${STRING[*]}" 0 0
# you can put a return $? if you want at the end, but not required

in general you should eliminate eval, which will not only speed up the execution, but as you can see makes the code more readable (and also shorter)

louigi600 05-07-2017 04:37 AM

Quote:

Originally Posted by pan64 (Post 5707303)
for example:
Code:

eval $(echo dialog --title \"$TITLE\" --yesno  \" ${STRING[*]}\" 0 0 ) && return 1 || return 0
# can be simplified by:
dialog --title "$TITLE" --yesno  " ${STRING[*]}" 0 0
# you can put a return $? if you want at the end, but not required

in general you should eliminate eval, which will not only speed up the execution, but as you can see makes the code more readable (and also shorter)

We have already discussed that ... it will go in the revised version.


All times are GMT -5. The time now is 11:54 AM.