print Index with each line in awk - linux

For the first time the select display the options and it works fine but when I break from screenTwo function to come into this menu (previuos) it ask me for the selection but does not display the options, how can I handle this?
PS3="Please make a selection => " ; export PS3
select var in `awk -F "#" '{print $4}' ${Temp_Config_File} | uniq` PREVIOUS
do
echo "\n`date +"%d%m%Y%H%M%S"` Daemon $var selected " >> $Log_File
if [ -z $var ] ; then echo "\n\tPlease enter a valid choice \n " ; continue
else
if [ $var = "PREVIOUS" ]; then
#removeFiles
break
fi
screenTwo $var
fi
done
First Option : Please give me your idea.
Second option : Capture the return of screenTwo and whenever it is
break use awk to print the index with $4. (like below , but I dont
like it)
if [ $breakStat -eq 99 ]; then
i=1
echo "\n\nPlease choose one of the following deamon you wish to Start/Stop\n\n"
awk -F "#" '{print $4}' Temp_OPDaemon_Config.cfg | uniq | while read line
do
echo "${i}) ${line}"
let i=i+1
done
echo "${i}) PREVIOUS"
fi
Thanks

this is what I did to handle it .
PS3="Please make a selection => " ; export PS3
select var in `awk -F "#" '{print $4}' ${Temp_Config_File} | uniq` PREVIOUS
do
echo "${Date_Time} Daemon $var selected \n" >> $Log_File
if [ -z $var ] ; then echo "\n\tPlease enter a valid choice \n " ; continue
else
if [ $var = "PREVIOUS" ]; then
#removeFiles
break
fi
while :
do
screenTwo $var
breakStat=$?
if [ $breakStat -eq 99 ]; then
break
elif [ $breakStat -eq 98 ]; then
continue
fi
done
if [ $breakStat -eq 99 ]; then
echo "\n\nPlease choose one of the following deamon you wish to Start/Stop\n\n"
awk -F "#" '{print $4 }' ${Temp_Config_File} | uniq | awk -F "#" '{print NR ") " $0} END {print NR+1") PREVIOUS"}'
fi
fi
done

Related

I need some assistance in figuring out how to retrieve files through the usage of my bash script

Although I was able to figure out my first script and get it to run, I am having issues with my second script. Basically I need to retrieve my deleted files and restore them in my created home directory. I was able to get some of question 2, and all of 3 and 4 to work successfully. The issue I have with question 2 is if I type up the file that I want to restore, it will pull up the file and inode number which is fine. However, if I run the script without the desired file, it will show a bunch of inodes and the command "Missing Operand". The missing operand command is one that I want since I created it in order to test that the files I want to restore exist. I have attached my code below. Again, I wonder what I got wrong. I did some of the suggestions shellcheck offered but I still got the same results.
Here is my code:
#!/bin/bash
#2.
fileName=$1
inode=$(ls -i $1 | cut -d " " -f1)
echo "safe_rm_restore $1_$inode"
#3.
function movingfile(){
if [ -e $HOME/deleted ] ;
then
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f3)
fi
}
movingfile $1
#4.
function safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
function restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f2) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?: word"
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
rm $(grep $1 $HOME/.restore.info | cut -d" " -f2)
mv $HOME/deleted $(grep $1/.restore.info | cut -d" " -f2)
fi
if [[ $word = "n" ]] ;
then
rm $1
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
function restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info | -d":" -f2)]];
then
$remove
fi
}
restored $1
I've followed the suggestions that you all gave me (and it moved me towards the right direction) but I still had some issues getting my operations to fully work. For instance, if no file name was given, my script was supposed to say Missing Operand but instead it gives all inode numbers in my file and my script freezes for sometime. Here is my updated second bash script. The indention looks great from my UNIX system but is somehow skewed when I transfer it on here. Thank you again!
#!/bin/bash
##2.
fileName="$1"
inode="$(ls -i $1 |cut -d" " -f1)"
echo "safe_rm_restore $1_$inode"
touch "$1"
##3.
movingfile(){
if [ -e $HOME/deleted ] ;
then
touch $1_$inode
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f4)
else
exit 1
fi
}
movingfile $1
##4.
safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f4) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?:" word
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
mv $1_$inode $HOME/project $(grep $1/.restore.info | cut -d" " -f4)
fi
if [[ $word = "n" ]] ;
then
rm -r $1_$inode
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info |cut -d":" -f4) ]];
then
$remove
fi
}
restored $1

How to use sed or awk command to set a variable based on the values of two other variables

I'm trying to write a bash script which will look for outdated entries in the conf file and update them with the new value.
The old conf file will have two entries(-CAR and -BIKE). For example,
#Following are the entries in the conf file
#-CAR yes/no default set to no
#-BIKE yes/no default set to no
-CAR yes
-BIKE no
Now this bash script should grep for those entries and replace them with a single entry as -DRIVING_LEVEL (car/bike/none).
The logic is as follows:
If -CAR is set to yes, then DRIVING_LEVEL will be "car".
If -CAR is set to no and -BIKE is set to yes, then DRIVING_LEVEL will be "bike".
If both -CAR and -BIKE are set to none, then DRIVING_LEVEL will be "none".
I have written the following script which does the exact thing.
#!/bin/bash
CONF_FILE="license.conf"
grep -w $CONF_FILE -e '-CAR' -e '-BIKE' > /dev/null
if [ $? -eq 0 ]
then
echo "Old values are present"
var=$(grep -w $CONF_FILE -e '-CAR')
if [ $? -eq 0 ]
then
temp="${var##*$'\n'}"
option=$(echo $temp | sed 's/.* //g')
echo $option
if [ "$option" == "yes" ]; then
car=1
elif [ "$option" == "no" ]; then
car=0
fi
echo "Deleting $var"
sed -i '/-CAR/d' $CONF_FILE
fi
var2=$(grep -w $CONF_FILE -e '-BIKE')
if [ $? -eq 0 ]
then
temp2="${var2##*$'\n'}"
option=$(echo $temp2 | sed 's/.* //g')
echo $option
if [ "$option" == "yes" ]; then
bike=1
#echo $temp
elif [ "$option" == "no" ]; then
bike=0
fi
echo "Deleting $var2"
sed -i '/-BIKE/d' $CONF_FILE
fi
if [ "$car" == "1" ]; then
driving_level="car"
elif [ "$bike" == "1" ]; then
driving_level="bike"
else
driving_level="none"
fi
echo "Appending -DRIVING_LEVEL $driving_level"
echo "-DRIVING_LEVEL $driving_level" >> $CONF_FILE
else
echo "No old values"
fi
The things is that I think this is too long and can be shortened using sed or awk commands. But I couldn't make it. I want it to be as short as possible.
Thanks in advance !
Note:
I have used temp="${var##*$'\n'}" to retrieve the last line which has the actual value because grep will give both the lines containing -BIKE.
I have used option=$(echo $temp | sed 's/.* //g') because there can be any number of spaces between -BIKE and yes/no.
$ awk '($0 ~ /-CAR.*yes$/){dl="car";exit} ($0 ~ /-BIKE.*yes$/){dl="bike"} END{print "-DRIVING_LEVEL",(dl)?dl:"none"}' license.conf
-DRIVING_LEVEL car
Brief explanation,
$0 ~ /-CAR.*yes$/: if "-CAR yes" is found, print the result directly (that's the reason I use exit here)
($0 ~ /-BIKE.*yes$/): if "-BIKE yes" is found, keep finding the follow up lines since there's possibility to find "CAR".
Print the result as "none" if nothing is found.
Your whole script can just be:
awk '1; /^-CAR/ && $2 == "yes" {DL="car"} /^-BIKE/ && $2 == "yes" {DL="bike"}
END{print "-DRIVING_LEVEL", DL}' DL=none license.conf
This just appends a value for DRIVING_LEVEL at the end (note that if both car and bike are "yes", this will select the last one in the file, but you didn't specify what behavior you want in that case.) If you want to suppress the output of the original values:
awk '/^-CAR/ && $2 == "yes" {DL="car"} /^-BIKE/ && $2 == "yes" {DL="bike"}
! (/^-CAR/ || /^-BIKE/)
END{print "-DRIVING_LEVEL", DL}' DL=none license.conf
To check for the existence of the original entries, you can do:
awk '/^-CAR/{DL=($2 == "yes" ? "car" : "none"); next}
/^-BIKE/{ if(DL== "unset" || DL == "none"){DL=($2 == "yes" ?"bike":"none")} next}
1
END{
if(DL=="unset") { print "missing values" > "/dev/stderr"; exit 1 }
else
print "-DRIVING_LEVEL", DL}' DL=unset license.conf
Although if entries are missing this will output the file before finally noticing and emitting the error message. Probably cleaner to pre-check the input.

Bash offer numberd results for selection to user

my script takes in a site name from the user.
./run_script <site>
./run_script cambridge
Its then allows the user to checkout, edit, and commit changes to the file, via the script.
However, some sites have two to six files.
So the script lists them as follows
You have more than one Cambridge file.
Please pick from the following:
cambridge1
cambridge2
cambridge3
user enters the word cambridge[1-3]
However, I'd like to assign a value to each variable, i.e, as follows.
Please choose the option you want:
1). cambridge1
2). cambridge2
3). cambridge3
user enters 1, 2, or 3, and it picks up the file.
The current code I have is :
echo $(tput setaf 5)
echo "Please choose from the following: "
echo -n $(tput sgr0)
find path/to/file/. -name *"$site"* | awk -F "/" '{print $5}' | awk -F "SITE." '{print $2}'
echo $(tput setaf 3)
read -r input_variable
echo "You entered: $input_variable"
echo $(tput sgr0)
Here's a fun way:
# save the paths and names of the options for later
paths=`find path/to/file/. -name "*$site*"`
names=`echo "$paths" | awk -F "/" '{print $5}' | awk -F "SITE." '{print $2}'`
# number the choices
n=`echo "$names" | wc -l`
[ "$n" -gt 0 ] || echo "no matches" && exit 1
choices=`paste <(seq 1 $n) <(echo "$names") | sed 's/\t/). /'`
echo "Please choose from the following: "
echo "$choices"
read -r iv
echo "You entered: $iv"
# make sure they entered a valid choice
if [ ! "$iv" -gt 0 ] || [ ! "$iv" -le "$n" ]; then
echo "invalid choice"
exit 1
fi
# name and path of the user's choice:
name_chosen=`echo "$names" | tail -n+$iv | head -n1`
path_chosen`echo "$paths" | tail -n+$iv | head -n1`

Switch case: Confusing error in "Syntax error: word unexpected (expecting "in")"

This is my code:
echo
echo "WELCOME"
echo "-------------------------------------------------"
while true
do
echo
echo "Select A Menu Option"
echo "1: Ancestry History"
echo "2: Who is Online"
echo "3: What Process Any User is Running"
echo "4: Exit"
read mOption
case $mOption in
1) echo
echo "The Ancestry Tree For Current Process is....";
ps -ef > processes
grep "ps -ef" processes > grepProcesses
awk '{print $2, $3}' processes > awkProcesses
PID=$(awk '{print $2}' grepProcesses)
echo $PID
SPID=$(awk '{print $3}' grepProcesses)
PID=$SPID
end=0
while [ $end != 1 ]
do
echo " | "
echo $SPID
PID=$SPID
SPID=$(grep ^"$PID " awkProcesses | cut -d' ' -f2)
if [ "$PID" = "1" ]
then
end=1
fi
done
rm processes
rm grepProcesses
rm awkProcesses
;;
2) echo
echo "Users Currently Online";
who | cut -d' ' -f1
;;
3) echo
echo "Select a Currently Online User to View their Processes:"
index=0
who | while read onlineUser
do
echo "$index-$onlineUser" who|cut -d' ' -f1>>userList
index=$((index+1))
done
awk '{ print $0 }' userList
read choice
if [ $choice ]
then
echo
echo ***Process Currently Running***
person=$(grep ^$choice userList |cut -d'-' -f2)
ps -ef >> process
grep $person process
else
echo You have made a mistake. Please start over.
fi
rm userList
rm process
;;
4) echo
echo "Exiting..."
exit 1;;
*)
echo
echo "Invalid Input. Try Again."
;;
esac
done
Each time I run it I just keep getting the syntax error "hmwk1.sh: 17: hmwk1.sh: Syntax error: word unexpected (expecting "in")"
I looked up different syntax examples and it seems that my code looks correct. But my trial and error gets me nowhere to fixing my code.
Could I be missing a parenthesis or quotation marks of some kind?
If you simply press return on the prompt
read mOption
case $mOption in
then $mOption is an empty token, making the shell see just
case in
which is a syntax error. If you add
test -z "$mOption" && continue
in the middle, if will repair that problem.

optimizing the while loop with awk command

Can any one suggest me how to optimize below while loop which is part of a shell script.
function setvars() {
CONN_TSMP="$1"
USER="$2"
DB="$3"
IP="$4"
HOST="$5"
return
}
while read line; do
TST=`grep -w $line $FILE1`
ID=`echo $line | tr -d '\"'`
VARS=$(echo ${TST} | awk -F '"' '{print $2 " " $10 " " $22 " " $20 " " $18 }')
setvars $VARS
if [ -z "$IP" ]; then
IP=`echo "$HOST"`
fi
if [ "$USER" == "root" ] && [ -z $DB ]; then
TARGET=/home/database/data1/mysql_audit/sessions/root_sec
FILE=`echo "$ID-$CONN_TSMP-$USER#$IP.txt"`
else
TARGET=/home/database/data1/mysql_audit/sessions/user_sec
FILE=`echo "$ID-$CONN_TSMP-$USER#$IP.txt"`
fi
ls $TARGET/$FILE
if [ $? -ne 0 ]; then
echo -e "################################################################ \n" >> "$TARGET/$FILE"
echo "$TST" | awk -F 'STATUS="0"' '{print $2}'| sed "s/[</>]//g" >> "$TARGET/$FILE"
echo -e "\n" >> "$TARGET/$FILE"
fi
awk -F '"' '/"'$line'"/ {print "\n======================================\nTIMESTAMP=" $2 "\nSQLTEXT=" $10}' $FILE3 >> "$TARGET/$FILE"
done < "$FILE4"
According to my observation awk is taking more time.
Can any one help me how to write optimize the above code by replacing it with awk code (an awk while loop which replace entire while loop shown above) or by removing awk or sed or grep which take more time.
1) In setvars(), Remove the double quotes around the assignments. The double quotes force the shell to rescan the values. This is minor, but in large shell scripts, it can add up to quite a bit of processing time.
2) You have multiple VAR=echo $SOMEVAL. Just assign the value: ID=$HOST
FILE="$ID-$CONN_TSMP-$USER#$IP.txt"
3) You are running an external program 'ls' to check and see if a file exists. Instead, use the builtin shell commands: if [ ! -f "$TARGET/$FILE" ]; then ...; fi. If you want the output, just do an: echo "$TARGET/$FILE".
4) Open the output file once. This is much faster, but can make maintenance of the script quite difficult. Since you only have 4 echo lines, it may not help that much.
exec 4>>"$TARGET/$FILE"
if [ ! -f "$TARGET/$FILE" ]; then
echo -e ... >&4
...
fi
awk -f ... >&4
exec 4>&-
It's not possible to optimize your awk without seeing the data it is processing. You appear to have a more modern shell as there is a $(...) construct. Replace any backtick usage with $(...).

Resources