LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   BASH - Running functions in an array and avoiding spaghetti monster like code? (https://www.linuxquestions.org/questions/programming-9/bash-running-functions-in-an-array-and-avoiding-spaghetti-monster-like-code-899338/)

Dimitriy 08-25-2011 03:17 AM

BASH - Running functions in an array and avoiding spaghetti monster like code?
 
Hi Folks,

I am writing an automation to share with a NAS community that is essentially an upgrade to my original version (which was line by line - it ran as you read; batch style with no functions or goto's). There is not specifically a need for this but I do it for fun of automating and streamlining my own setup of the NAS and pick up a thing or two occasionally that helps me out in my day job.

This new version will be about 1500 lines with about 20+ functions (or sequences as I like to call them - thats how I am currently using functions). I am looking to introduce command line argument(s) handling to the script. However the way I imagine the command line arguments would be used will be for NOT doing certain portions of the script. Essentially user runs the script: myscript.sh --no_orange --no_peach (this would do everything but peach and orange function sequences)

Basic Code (this is exact syntax I am using) looks something like this:
Code:

#!/bin/bash

intro () { echo "Start my fruit application installer"; }
installapple () { echo "Apple are installed"; }
installorange () { echo "Orange are installed"; }
installpeach () { echo "Peach is installed"; }
finished () { echo "Finished running this fruity automation"; }

runarray[1]=intro
runarray[2]=installapple
runarray[3]=installorange
runarray[4]=installpeach
runarray[5]=finished


for i in $*
do
        case $i in
            --no_apple)
                #installapple is in index 2 of the array. Remove it and run the array
                unset runarray[2]
echo "Skipping Apple"
                ;;
            --no_orange)
                #installorange is in index 3 of the array. Remove it and run the array
                unset runarray[3]
echo "Skipping Orange"
                ;;
            --no_peach)
                #installpeach is in index 4 of the array. Remove it and run the array
                unset runarray[4]
echo "Skipping Peach"
                ;;
            --default)
                echo "Nothing defined - All fruits will be installed"
                ;;
            *)
                echo "Did NOT recognize the command line arguements - No FRUITY APPS FOR YOU. Exiting"
                                exit
                ;;
          esac
done

${runarray[0]}
${runarray[1]}
${runarray[2]}
${runarray[3]}
${runarray[4]}
${runarray[5]}

The questions I have today are:

A) Will this work? I am not sure if I can just so easily put function commands into an array and just say "myarray" and that would run all the items in the array in order. Currently I am running each individual array index but was wonder if there was easy way to call them all using just one line (like ${runarray[all]}?

B) Is there a better way? I imagine could do an if statements if bash supports [switch] statements (thinking powershell/.net). If you think this way works just fine please share that too as its always good to hear. Please note when considering this question my scripting skills are modest at best and not sure if my modest brain can comprehend the really fancy stuff yet - looking for relatively simple alternatives if needed.

C) Is there a gaping hole in my logic? Common request I got about the old script was the option to NOT install certain applications/packages that my script would install. I thought it would be logical, considering the large number of applications/packages looking available to be installed, that I would make a subtractive handling vs mentioning each application/package user wanted.

appreciate all comments,
dpc

grail 08-25-2011 05:02 AM

Personally I do not like the idea of attempting run something even if it is not there, ie the array items at the end run no matter what.

Here is an alternative you can play with ... please understand I am not saying yours is in anyway wrong:
Code:

#!/bin/bash

switch_reg='--no_(apple|orange|peach)'

for args
do
    if [[ ! "$args" =~ $switch_reg ]]
    then
        echo "Inavalid switch :- $args. Please start again"
        exit
    fi
done

intro () { echo "Start my fruit application installer"; }
installapple () { echo "Apple are installed"; }
installorange () { echo "Orange are installed"; }
installpeach () { echo "Peach is installed"; }
finished () { echo "Finished running this fruity automation"; }

intro

for j in install{apple,orange,peach}
do
    if [[ $@ =~ --no_${j#install} ]]
    then
        echo "Skipping ${j#install}"
    else
        $j
    fi
done

finished

I have also heard that it is frowned upon to run commands stored in variables, but I believe it is a personal choice.

sundialsvcs 08-25-2011 09:24 AM

Don't want spaghetti?

Don't use Bash.

You've got a dozen or more good programming languages at your disposal, and no one but you can tell what language(s) you used to write a script. No one, that is, except you, your team, and those who must follow in your footsteps after you (poor sot...) unexpectedly "failed the taxi test."

Writing a real program? Use a real language. That is to say, one that was engineered to do the job.

(P.S. Don't take my words personally. Not at all. I am expressing an engineering opinion, otherwise known as "Tools for the Job." I am expressing an experienced opinion about the (un-)suitability of the tools, not the tool users.)

Dimitriy 08-31-2011 01:10 PM

Its been a busy week. Thanks for all the replies folks I will look at them unfortunately later busy busy week.

thanks,
dpc

chrism01 08-31-2011 08:53 PM

Consider getopts http://linux.die.net/man/1/bash or http://linux.die.net/man/1/getopt


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