LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bash script parameters and logic (https://www.linuxquestions.org/questions/programming-9/bash-script-parameters-and-logic-939967/)

asistant 04-15-2012 10:35 PM

bash script parameters and logic
 
Hello everyone,

I am trying to create a basic script with the following requirements:

When no command line arguments at all are present, the script will print a helpful "Usage" message listing the possible options and arguments, and exit. I think i got this one.
Example: sh myscript.sh

The script's default function when no options are given on the command line, but a <name> is supplied, is to print all lines in my address_book file.
Example: sh myscript.sh Bill

If the '-a' option is present, the script will prompt for the data items in the record (name,and email address), construct a data record with the appropriate format, and add it to the 'address_book' file.
Example: sh myscript.sh -a

If the '-b' option is present, the script will mail a personalized greeting to the email address of every person in 'address_book' whose day of birth is today.
Example: sh myscript.sh -b

I am new to bash scripting language and I am having trouble to construct script logic.


I create the first part it worked fine and I am trying to construct the rest part. Here is what i have so far.

Code:

[asistant@myserver]$ cat test5
#!/bin/bash

function help_menu {
    echo "Usage: $0 [-a] [-b ] [<name>]";
  echo "Options";
  echo "$0 [-a] Add record to address book";
  echo "$0 [-b] Send personalized greeting whose birthday is today";
  echo "$0 [<name>] search for specified name"
}

function search_name {
Name=$1
    grep $Name ~/address_book;
    echo " do something more"
}

if test $# -eq 0;
 then
    help_menu

elif [ "$Name"="-b" ];
 then
    search_name "$Name"         
    exit 0
fi

exit 0

can somebody help me with this or show me sample?

Any input greatly appreciated.

Thanks.

konsolebox 04-15-2012 11:03 PM

How do you add record to the address book and how do you send a personalized greeting? I mean the commands.

catkin 04-15-2012 11:59 PM

It would be simpler to separate command line parsing (and error trapping) from the actions. Assuming you would like to add a -h option to get verbose help, then something like this
Code:

    # Parse command line
    # ~~~~~~~~~~~~~~~~~~
    emsg=''
    nl=$'\n'    # newline
    name=
    opt_a=
    opt_b=
    while getopts abh opt 2>/dev/null
    do
        case $opt in
            a )
                opt_a=true
                ;;
            b )
                opt_b=true
                ;;
            h )
                usage -v
                exit 0
                ;;
            * )
                emsg="${nl}Invalid option '$opt'"
        esac
    done

    # Test for optional argument
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~
    shift $(( $OPTIND-1 ))
    if [[ $1 != '' ]]; then
      name=$1
      shift
    fi

    # Test for extra arguments
    # ~~~~~~~~~~~~~~~~~~~~~~~~
    if [[ $* != '' ]]; then
        emsg="${nl}Invalid extra argument(s) '$*'"
    fi

    # Report any errors
    # ~~~~~~~~~~~~~~~~~
    if [[ $emsg != '' ]]; then
        echo "$emsg" >&2
        usage
        exit 1
    fi

if [[ $opt_a != '' ]]; then
    <whatever>
fi

if [[ $opt_b != '' ]]; then
    <whatever>
fi

if [[ $name != '' ]]; then
    <whatever>
fi


grail 04-16-2012 01:15 AM

May I also suggest for the usage / help function that you have a look at here documents. I find this particularly helpful, especially
if the size of the information will grow or vary.

Also, whilst getopts presented by catkin is fine, if you wish to play a bit more with bash you could produce your own simple parser to search for strings starting with a hyphen
and use a similar case to set the appropriate options:
Code:

for arg
do
    if [[ ${arg:0:1} == "-" ]]
    then
        <do case here>
    else
        OTHER+=( "$arg" )
    fi
done


Reuti 04-16-2012 06:33 AM

Quote:

Originally Posted by grail (Post 4653756)
Also, whilst getopts presented by catkin is fine, if you wish to play a bit more with bash you could produce your own simple parser to search for strings starting with a hyphen
and use a similar case to set the appropriate options:

While parsing by shell programming might be more portable across different shells, the getopts builtin in bash has the advantage to allow to concatenate options, i.e. -ab is the same like -a -b.

grail 04-16-2012 10:23 AM

Quote:

While parsing by shell programming might be more portable across different shells, the getopts builtin in bash has the advantage to allow to concatenate options, i.e. -ab is the same like -a -b.
And a little coaxing in a loop over the string after the hyphen can perform the same ... I just like to play ;)

I would add that long options are also handled a little easier than with getopts.

Nominal Animal 04-16-2012 07:09 PM

Quote:

Originally Posted by Reuti (Post 4653978)
While parsing by shell programming might be more portable across different shells, the getopts builtin in bash has the advantage to allow to concatenate options, i.e. -ab is the same like -a -b.

Quote:

Originally Posted by grail (Post 4654179)
I would add that long options are also handled a little easier than with getopts.

As it happens, I wrote a skeleton script along those very lines recently myself.

It handles -a a-param -b the same as -ab a-param, and also supports long options with or without values, i.e --help, --type=value or --type value .

I'm sure sharp minds here could find ways to enhance it, though. :study:

asistant 04-17-2012 10:07 AM

Than you very much everyone for the help and inputs.

Here what i have so far it looks like it is working fine at this point now I am trying to fill each functions to perform actual work.

Code:

#!/bin/bash

function display_help {
    echo "Usage: $0 [-a] [-b ] [<name>]";
        echo "OPTIONS:";
        echo "                [-a] Add record to address book";
        echo "                [-b] Send personalized greeting whose birthday is today";
        echo "                [<name>] search for specified name"
}

function search_name {
addressfile=~/myaddrbook

    grep "$1" $addressfile | tr ":" " "
        echo
            echo "listed above"
}

function add_record {
    echo "Adding Record to database";
        echo "do more"
}

function send_b_greetings {
    echo "Sending birthday greetings";
        echo "Still working progress"
}


if [ $# -eq 0 ]; then
    display_help
    exit 1
fi   

if [ -n "$1" ]; then
        search_name
fi

# Now parse command line arguments

while getopts "ab" var;
do
    case "$var" in
        a) add_record;;
        b) send_b_greetings;;
        \?) display_help; exit 1;;
    esac
done

Here is my address sample book format:
Elizabeth:Miller:A:55 W. Main Street:Camp Hill:CA:94500:717-502-0334:elizabeth.miller@wolpublishing.com:01/18/1980
John:Johnson:A:2155 North Street:Harrisburg:PA:17101:717-233-1100:john.johnson@wolpublishing.com:02/16/1967

I am having trouble with grep command in my function

Code:

function search_name {
addressfile=~/myaddrbook

    grep "$1" $addressfile | tr ":" " "
        echo
            echo "listed above"
}

when i pass "$1" argument to grep command it list display whole file rather than specific record passed from the script command line.

[asistant@myserver ~]$ ./test3 John

any idea?

Thanks you.

grail 04-17-2012 10:36 AM

I would suggest putting set -xv just after the shebang and you will see the reason for this. As a nudge in the right direction, functions and scripts behave similarly when called with parameters :)

asistant 04-17-2012 10:38 AM

grail, sorry how do you do that?

Nominal Animal 04-17-2012 12:32 PM

Quote:

Originally Posted by grail (Post 4655177)
As a nudge in the right direction, functions and scripts behave similarly when called with parameters :)

Quite.

Put another way, $1 in a function refers to the first parameter to the function.

Bluntly: it does not refer to the first positional parameter the caller might have, as asistant seems to think. Functions only see their own positional parameters.

($0 is special, though: it describes the script name. For Bash sripts, it gets set to whatever file Bash is executing.)

grail 04-17-2012 12:57 PM

Quote:

grail, sorry how do you do that?
So the first 2 lines of the script should look like:
Code:

#!/bin/bash
set -xv

<rest of your script here>


asistant 04-17-2012 01:30 PM

thanks grail I am getting closer. Here is what happens

When i execute the script like this;

[asistant@myserver]$ ./test4 John

Code:

if [ -n "$1" ]; then
  search_name
fi
+ '[' -n John ']'
+ search_name
+ addressfile=/home/asistant/myaddrbook
+ grep '' /home/asistant/myaddrbook
Elizabeth:Miller:A:55 W. Main Street:Camp Hill:CA:94500:717-502-0334:elizabeth.miller@wolpublishing.com:01/18/1980
John:Johnson:A:2155 North Street:Harrisburg:PA:17101:717-233-1100:john.johnson@wolpublishing.com:02/16/1967
+ echo

It knows that i passed arguments John=$1 but inside the function it kind of clears $1 when i pass to $1 to grep command.

any ideas?

Thanks you.

grail 04-17-2012 03:03 PM

Quote:

any ideas?
Yes ... re-read posts #9 & 11 again carefully :)

asistant 04-18-2012 08:58 AM

thank for pointing me right direction. Here what i come up with.
added
#Make arguments global to the script.
args=("$@")

changed the function as;
#Create function for searching name.
function search_name {
addressfile=~/myaddrbook
grep -i ${args[0]} $addressfile | tr ":" " "
}

Here is my new version of the script.

Code:

#!/bin/bash
#
#Make arguments global to the script.
args=("$@")

#Create function for displaying help.
function display_help {
    echo "Usage: $0 [-a] [-b ] [<name>]";
        echo "OPTIONS:";
        echo "          [-a] Add record to address book";
        echo "          [-b] Send personalized greeting whose birthday is today";
        echo "          [<name>] search for specified name";
        exit 1
}

#Create function for searching name.
function search_name {
addressfile=~/myaddrbook
    grep -i ${args[0]} $addressfile | tr ":" " "
}

#Create function for adding new records.
function add_record {
    echo "Adding Record to database";
        echo "          [<name>] search for specified name"
}

#Create function for sending greetings.
function send_b_greetings {
    echo "Sending birthday greetings";
        echo " [<name>] search for specified name"
}


#If no argument or parameter specified dislplay help menu.
if [ $# -eq 0 ]; then
    display_help
fi

#Now parse command line arguments using getopts.
while getopts "ab" var;
do
    case "$var" in
        a) add_record; exit 0;;
        b) send_b_greetings; exit 0;;
        \?) display_help; exit 1;;
    esac
done

search_name
exit 0

Thank you very much for your help.


All times are GMT -5. The time now is 03:59 AM.