LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-15-2012, 10:35 PM   #1
asistant
LQ Newbie
 
Registered: Oct 2003
Location: Ankara
Distribution: Redhat
Posts: 17

Rep: Reputation: 0
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.

Last edited by asistant; 04-15-2012 at 10:36 PM.
 
Old 04-15-2012, 11:03 PM   #2
konsolebox
Senior Member
 
Registered: Oct 2005
Distribution: Gentoo, Slackware, LFS
Posts: 2,248
Blog Entries: 8

Rep: Reputation: 235Reputation: 235Reputation: 235
How do you add record to the address book and how do you send a personalized greeting? I mean the commands.
 
Old 04-15-2012, 11:59 PM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
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
 
1 members found this post helpful.
Old 04-16-2012, 01:15 AM   #4
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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
 
Old 04-16-2012, 06:33 AM   #5
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 15.2
Posts: 1,339

Rep: Reputation: 260Reputation: 260Reputation: 260
Quote:
Originally Posted by grail View Post
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.
 
Old 04-16-2012, 10:23 AM   #6
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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.
 
Old 04-16-2012, 07:09 PM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by Reuti View Post
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 View Post
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.
 
1 members found this post helpful.
Old 04-17-2012, 10:07 AM   #8
asistant
LQ Newbie
 
Registered: Oct 2003
Location: Ankara
Distribution: Redhat
Posts: 17

Original Poster
Rep: Reputation: 0
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.
 
Old 04-17-2012, 10:36 AM   #9
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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
 
Old 04-17-2012, 10:38 AM   #10
asistant
LQ Newbie
 
Registered: Oct 2003
Location: Ankara
Distribution: Redhat
Posts: 17

Original Poster
Rep: Reputation: 0
grail, sorry how do you do that?
 
Old 04-17-2012, 12:32 PM   #11
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Quote:
Originally Posted by grail View Post
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.)

Last edited by Nominal Animal; 04-17-2012 at 12:43 PM. Reason: Fixed the quoted note to describe Bash behaviour.
 
1 members found this post helpful.
Old 04-17-2012, 12:57 PM   #12
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
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>
 
1 members found this post helpful.
Old 04-17-2012, 01:30 PM   #13
asistant
LQ Newbie
 
Registered: Oct 2003
Location: Ankara
Distribution: Redhat
Posts: 17

Original Poster
Rep: Reputation: 0
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.
 
Old 04-17-2012, 03:03 PM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Quote:
any ideas?
Yes ... re-read posts #9 & 11 again carefully
 
1 members found this post helpful.
Old 04-18-2012, 08:58 AM   #15
asistant
LQ Newbie
 
Registered: Oct 2003
Location: Ankara
Distribution: Redhat
Posts: 17

Original Poster
Rep: Reputation: 0
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.
 
  


Reply

Tags
logic, parameters



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] bash script sed -r -i and -e parameters charu Programming 10 05-06-2011 06:28 AM
nested loop-bash script- issue on logic yathin Linux - Newbie 6 05-31-2010 06:30 AM
Passing parameters to bash script Kamikazee Programming 4 10-01-2005 06:41 AM
Passing Parameters to Bash Script mooreted Linux - Software 3 04-05-2004 09:08 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:49 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration