ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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
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
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
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.
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.
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
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.
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
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
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.
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.
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
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.