I am new to bash scripting. I have a script that i am working on for a school project and its not working as expected. I keep receiving a error on my if then statements.
#!/bin/bash
echo –e “Would you like to add a new employee’s information? y/n \n”
read EMPLOYEE
if [ $EMPLOYEE = “y” –o $EMPLOYEE = “Y” ]
then
echo –e “Please enter employee’s first name \c”
read FIRST
echo –e “Please enter employee’s last name \c”
read LAST
echo –e “Please enter empolyee’s ID \c”
read ID
echo –e “$FIRST\t$LAST\t$ID” >> database
fi
echo –e “Would you like to search for an employee? y/n \n”
read SEARCH
if [ $SEARCH = “y” –o $SEARCH = “Y” ]
then
echo –e “Enter the first name, last name or employee ID to search for. \c”
read WORD
grep “$WORD” database
fi
With even a bash version 3 the following should work as you intended and be somehow shellitical correct ;-)
#!/bin/bash
printf "Would you like to add a new employee’s information? y/n \n"
read -r EMPLOYEE
if [ "$(tr '[:upper:]' '[:lower:]' <<<"$EMPLOYEE")" = "y" ]
then
printf "Please enter employee’s first name : \c"
read -r FIRST
printf "Please enter employee’s last name : \c"
read -r LAST
printf "Please enter empolyee’s ID : \c"
read -r ID
printf "%s\t%s\t%s" "$FIRST" "$LAST" "$ID" >> database
fi
printf "Would you like to search for an employee? y/n \n"
read -r SEARCH
if [ "$(tr '[:upper:]' '[:lower:]' <<<"$SEARCH")" = "y" ]
then
printf "Enter the first name, last name or employee ID to search for. : \c"
read -r WORD
grep "$WORD" database
fi
Notes on refactoring/repair:
Do not rely on echo -e in most cases printf works better and looks more like coding,
use read -rto mot mangle backslashes on input,
quote variables from input (with real ASCII quote characters), as the shell parser otherwise does funny things,
do not test against y and Y but simply lowercase the string received to only compare one variant.
Use some indent concept to track, and
use a shell linter as suggested by a commenter already (that one works nicely currently).
The above code does have no errors indicated in the above mentioned linter.
Small task for as exercise for the reader (thanks andlrc :)
Use lowercase variable names and I amend meaningful names
Enjoy the learning of the shell coding!
Related
I have wrote a program in bash, where there will be details of the students in a file and on passing input as roll no to it I need to edit that particular line in the file.
But when I tried by passing the roll no, it is displaying the whole file to me for editing when condition matches.
Here is my program:
#!/bin/bash
input="/home/kalyan/Desktop/Exercise/studet.txt"
while IFS=":" read -r rollno name s1 s2 s3
do
echo "$rollno"
done < "$input"
read -p "Enter the Roll No:" rollno1
if [ "$rollno"-eq"$rollno1" ]; then
nano studet.txt
cat studet.txt
else
echo "Doesn't match"
fi
or this program
#!/bin/bash
file="/home/kalyan/Desktop/Exercise/"
FILE="/home/kalyan/Desktop/Exercise/studet.txt"
echo "file to be processed $FILE"
cat $FILE
echo "Reading Roll Number:"
read -r rollno;
if grep $rollno /home/kalyan/Desktop/Exercise/studet.txt
then
echo "Roll No exists"
else
echo "Roll No doesn't exists"
fi
Here I'm trying to get a record of a student based on the roll no as input.
when the roll no matches I'm displaying his rollno, name, marks of three subjects(s1,s2,s3).
Now I need to edit the line which matches the criteria.
Not sure I understand fully what you are doing, but I would do (based on title of the question):
line_number=`grep -n "^$rollno\$" /tmp/a | cut -d : -f 1 "$input"`
nano +"$line_number" studet.txt
Is this last file the same as $input?
I'am not sure if this what you want to have... but say that you want to change a user name depending on its id given as input while running the program:
studet.txt
1:surname1:name1:age1
2:surname2:name2:age2
3:surname3:name3:age3
script.sh
#!/bin/bash
read -p "Enter the Roll No:" rollno
read -p "Enter new name:" name
awk -F ":" -v roll="$rollno" -v name="$name" 'BEGIN {OFS = ":"} $1==roll {$3=name}1' studet.txt > testfile.tmp && mv testfile.tmp studet.txt
The above script will ask the user to pass rollno (exp 1) and name values.
Then awk commad will check if the given rollno exists in the file first fileds (file will be splited into fields using : separator), if this rollno exists the third field of the same line will be changed by the value name the user passed before.
Give it a try by passing 1 and then some string and then check your file.
Hi I want to make a script that inserts contacts to a .csv file. It asks the user to type First Name, Last Name, and Phone number and then the output will be saved in a file named contacts.csv.
For example : John,Dawson,2102983187
Tried this but want to separate output with commas as it's on the example and it has to be in a loop.
#!/bin/bash
IFS=','
touch contacts.csv
echo "What's your contact's first name?"
read fname
echo "$fname" | grep '^[[:upper:]]\+[a-z]\{0,\}' >> contacts.csv
echo "What's your contact's last name?"
read lname
echo "$lname" | grep '^[[:upper:]]\+[a-z]\{0,\}' >> contacts.csv
echo "Whats your contact's phone number"
read phone
echo "$phone" | grep '[0-9]\{10\}$' >> contacts.csv
#!/bin/ksh
read fname?"What's your contact's first name? "
read lname?"What's your contact's last name? "
read phone?"What's your contact's phone number? "
[[ $fname =~ ^[[:upper:]][a-z]+$ ]] || { echo "$fname should be uppercase first char followed by lowercase chars" ; exit 1; }
[[ $lname =~ ^[[:upper:]][a-z]+$ ]] || { echo "$fname should be uppercase first char followed by lowercase chars" ; exit 2; }
[[ $phone =~ ^[[:digit:]]+$ ]] || { echo "$fname should be digits only" ; exit 3; }
echo "$fname,$lname,$phone" >> contacts.csv
Changing IFS isn't necessary. IFS=Input separator, and from your checks, I assume, that you don't want , in your input.
Read can provide a prompt, no need to use echo.
I would check all inputs first, and then write to output.
If you put the block between
while true; do
...
done
An empty input will stop the processing
So I have a file called "nouns" that looks like this:
English word:matching Spanish word
Englsih word:matching Spanish word
..etc etc
I need to make a program that list all the English words with an option to quit. The program displays the English words and ask the user for the word he wants translated and he can also type "quit" to exit.
This is what I have so far that shows me the list in English
select english in $(cut -d: -f1 nouns)
do
if [ "$english" = 'quit' ]
then
exit 0
fi
done
I know that I need to run a command that pulls up the second column (-f2) by searching for the corresponding English word like this
result=$(grep -w $english nouns|cut -d: -f2)
My end result should just out put the corresponding Spanish word. I am just not sure how to get all the parts to fit together. I know its based in a type of "if" format (I think) but do I start a separate if statement for the grep line?
Thanks
You need a loop in which you ask for input from user. The rest is putting things together with the correct control flow. See my code below:
while :
do
read -p "Enter word (or quit): " input
if [ "$input" = "quit" ]; then
echo "exiting ..."
break
else
echo "searching..."
result=$(grep $input nouns | cut -d ':' -f 2)
if [[ $result ]]; then
echo "$result"
else
echo "not found"
fi
fi
done
dfile=./dict
declare -A dict
while IFS=: read -r en es; do
dict[$en]=$es
done < "$dfile"
PS3="Select word>"
select ans in "${!dict[#]}" "quit program"; do
case "$REPLY" in
[0-9]*) w=$ans;;
*) w=$REPLY;;
esac
case "$w" in
quit*) exit 0;;
*) echo "${dict[$w]}" ;;
esac
done
You want to run this in a constant while loop, only breaking the loop if the user enters "quit." Get the input from the user using read to put it in a variable. As for the searching, this can be done pretty easily with awk (which is designed to work with delimited files like this) or grep.
#!/bin/sh
while true; do
read -p "Enter english word: " word
if [ "$word" = "quit" ]; then
break
fi
# Take your pick, either of these will work:
# awk -F: -v "w=$word" '{if($1==w){print $2; exit}}' nouns
grep -Pom1 "(?<=^$word:).*" nouns
done
I am creating a simple phonebook using unix shell scripts. I have gotten all of my functions to work except the removal of a contact after it has been created. I have tried combining grep and sed in order to accomplish this, but cannot seem to get over the hump. The removal shell i've tried is as follows.
#!/bin/sh
#removeContact.sh
echo “Remove Submenu”
echo “Please input First Name:”
read nameFirst
echo “Please input Last Name:”
read nameLast
x=$(grep -e “$nameFirst” -e “$nameLast” ContactList)
echo $x
sed '/'$x'/ d' ContactList;
echo “$nameFirst $nameLast is removed from your contacts”
exit 0
I'm not sure if I am declaring x incorrectly, or if my syntax is wrong when sed is used.
Any help would be greatly appreciated. Thank you.
#!/bin/bash
ContactList="contacts.txt"
export ContactList
exit=0
while [ $exit -ne 1 ]
do
echo "Main Menu"
echo "(a) Add a Contact"
echo "(r) Remove a Contact"
echo "(s) Search a Contact"
echo "(d) Display All Contact’s Information"
echo "(e) Exit"
echo "Your Choice?"
read choice
if [ "$choice" = "a" ]
then
./addContact.sh
elif [ "$choice" = "r" ]
then
./removeContact.sh
elif [ "$choice" = "s" ]
then
./searchContact.sh
elif [ "$choice" = "d" ]
then
./displayContact.sh
elif [ "$choice" = "e" ]
then
exit=1
else
echo "Error"
sleep 2
fi
done
exit 0
#!/bin/sh
#addContact.sh
ContactList="contacts.txt"
echo “Please input First Name:”
read nameFirst
echo “Please input Last Name:”
read nameLast
echo “Please input Phone Number:”
read number
echo “Please Input Address”
read address
echo “Please input Email:”
read email
echo $nameFirst:$nameLast:$number:$address:$email>> ContactList;
echo "A new contact is added to your book."
exit 0
sed '/'$x'/ d' ContactList
won't remove anything from the file ContactList, it will simply output the changes to standard output.
If you want to edit the file in-place, you'll need the -i flag (easy) or to make a temporary file which is then copied back over ContactList (not so easy, but needed if your sed has no in-place editing option).
In addition, since ContactList is a shell variable referencing the real file contacts.txt, you'll need to use $ContactList.
And, as a final note, since you're using the full line content to do deletion, the presence of an address like 1/15 Station St is going to royally screw up your sed command by virtue of the fact it contains the / character.
I would suggest using awk rather than sed for this task since it's much better suited to field-based data. With the record layout:
$nameFirst:$nameLast:$number:$address:$email
you could remove an entry with something like (including my patented paranoid perfect protection policy):
cp contacts.txt contacts.txt.$(date +%Y.%m.%d.%H.%M.%S_$$)
awk <contacts.txt >tmp.$$ -F: "-vF=$nameFirst" "-vL=$nameLast" '
F != $1 || L != $2 {print}'
mv tmp.$$ contacts.txt
I keep getting an error on line 22: [!: command not found
My script Asks for a name, phone number, and date of birth and then amends these details to a comma separated value file called “birthday.csv”.
It then Sorts “birthday.csv” by date of birth. The newly sorted file is then displayed and calculates their age.
Can someone take a look at my script and see why this is popping up.
#!/bin/bash
a=0
while [ $a -lt 2 ];
do
echo Please enter a first name
read firstName
echo Please enter last name
read lastName
echo Please enter phone number
read phoneNumber
echo Please enter date of birth - format dd/mm/yyyy
read dob
echo "$firstName,$lastName,$phoneNumber,$dob" >> userBirthdays.csv
echo If you would like to add another person press 1 or enter 2 to proceed
read a
done
INPUT=./userBirthdays.csv
OLDIFS=$IFS
IFS=","
[! -f INPUT] & while read Name Surname Telephone DOB
do
birthMonth=${DOB:0:2}
birthDay=#10${DOB:3:2}
birthYear=${DOB:6:4}
currentDate=`date +%d/%m/%Y`
currentMonth=${currenDate:0:2}
currentDay=#10${currentDate:3:2}
currentYear=${currentDate:6:4}
if [[ "$currentMonth" -lt "$birthMonth" ]] || [[ "$currentMonth" -eq "$birthMonth" && "$((#10$currentDay))" -lt "$((#10$birthDay))" ]]
then
let Age=currentYear-birthYear-1
else
let Age=currentYear-birthYear
fi
echo "Name : $Name"
echo "Surname : $Surname"
echo "Telephone : $Telephone"
echo "DOB : $DOB"
echo "Age : $Age"
echo "##########################################"
done < $INPUT
IFS=$OLDIFS
echo $DATE
exit 0;
Thank you in advance
you need a space between between the [ and ! chars, i.e.
[ ! -f $INPUT ] && while read ....
#^-^--------^-^---^------------
Note that you almost certainly want two '&' chars, as in my correction.
Thanks to #GordonDavisson for another '$' ;-)
IHTH
Separate [ and ! with a space, so [ will be a command, and ! will be its first argument, as you meant them to be.
(Not sure there are no other problems).