Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
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.
i really new in linux and just heard about shell scripting couple days ago..
i did exercises on linux in online tutorial but as a beginner, i'm facing problems in developing the script as there are errors that sometimes i dun have any idea on how to solve it.What i'm doing now is not homework, but i had been assigned to develop some system in linux.
i appreciate if there are people that willing to guide me on this matter.
my problem currently is on sub-string matter, where i need to read the line from file/directory and based on the line retrieved,i need to seperate the information in the line and assign as variable..
below are my script:
(the script reside in test.sh)
!/bin/sh
dir=/home/user/input/test.log #(this is the input file)
msg=`tail -1 $dir`
#(it will take only the last line as log file will be updated every day)
echo "$msg"
thus, the output something like this:
file_name successfully ran on Mon Jul 12 23:15:00 SST 2009.
now, what i need to do is to extract certain information from that line which is the name, date, time and the status
the desired output is:
name date time status
file_name Mon Jul 12 23:15:00 success
so,my next step is to identify the sub-string and assigned as variable first in order to parse the info and output it.
thus,my script is:
!/bin/sh
dir=/home/user/input/test.log #(this is the input file)
msg=`tail -1 $dir`
#(it will take only the last line as log file will be updated every day)
sub= $msg
name=${msg:0:8}
echo "$msg"
echo "name"
but i received error message which is
./test.sh[10]: name=${msg:0:8}: The specified substitution is not valid for this command.
As jlinkels points out it's probably because you aren't using the bash shell (substrings are specific to bash).
Your first line should be:
Code:
#!/bin/bash
To ensure script is run with bash
If you don't have a space in the file_name, time or status strings, using shell pattern removal should work quite well:
Code:
name=${msg%% *} # remove 1st space add all following
status=${msg#* } # remove 1st space and all proceeding
status=${status%% *} # remove 1st space add all following
datetime=${msg##*ran on } # remove "ran on " and all proceeding
datetime=${datetime%% SST *} # remove " SST " and all following
time=${datetime##* } # remove last space and all proceeding
date=${datetime% *} # remove last space and all following
Last edited by simon.sweetman; 07-13-2010 at 11:23 PM.
ok...i've edited my script and i got my desired output..
but the position of the string is always changes..Thus the script is no longer efficient.It may output wrong result. i'm thinking of creating a script that can read the exact sub-string that i wanted...let say from the whole line, i want to capture only "my file name"..instead of i have to set the position.
maybe in the log file, the last line has long/many words,so i just wanted to capture certain word in order for me to assign it as variable..
i've tried to search and did some try an error but still doesn't work.. any idea?
By position I presume you mean where the string starts or finishes but not where it is contained in the string?
If yhis is the case I would suggest using awk to return the required field.
Based on your first example this could look like:
So I am guessing you mean if your first example changed and the actual file name is "file name".
If this is the case, none of your other options were going to work any better. You will need one of the following:
1. valid delimeter so as to parse the information
2. prior knowledge of the exact length of each item
You might be able to use the status sting to align things for example if the string is always "successfully ran on" or "unsuccesfully run on" the following should work:
Code:
name=${msg%% unsuccesfully *}
status=failed
if [ ${#name} -eq ${#msg} ]
then
# length of string is same as original message
# ie replace matched nothing - assume success string
status=success
name=${msg%% successfully *}
fi
datetime=${msg##*ran on } # remove "ran on " and all proceeding
datetime=${datetime%% SST *} # remove " SST " and all following
time=${datetime##* } # remove last space and all proceeding
date=${datetime% *} # remove last space and all following
simon.sweetman,
i don't really understand one of the line;
if [ ${#name} -eq ${#msg} ] in
name=${msg%% unsuccesfully *}
status=failed
if [ ${#name} -eq ${#msg} ]
then
# length of string is same as original message
# ie replace matched nothing - assume success string
status=success
name=${msg%% successfully *}
fi
Ok I'll try and explain (numbered for ease of reference):
Code:
1 name=${msg%% unsuccesfully *}
2 status=failed
3 if [ ${#name} -eq ${#msg} ]
4 then
5 # length of string is same as original message
6 # ie replace matched nothing - assume success string
7 status=success
8 name=${msg%% successfully *}
9 fi
Line 1 removes everything from just before " unsuccesfully " to the end of the string. So after 1 name will have the filename if the string contains " unsuccesfully", or the whole value of msg if the string dosn't (nothing being removed because of nonmatch).
line 3 now compares the length of name with the length of msg, they will be equal if nothing was replaced in line 1 (ie string doesn't contain " unsuccesfully ").
We could also have used if [ "$name" = "$msg" ] here (note -eq is the numeric compare and = is the string compare). Lines 3 and 4 deduce if msg doesn't contain "unsuccesfully" then it must contain "sucessfully" (assumption is that there must be one or the other).
Try playing around from within the shell, just assign msg and then echo anything you want to try out eg:
Code:
$ msg="file name successfully ran on Mon Jul 12 23:15:00 SST 2009"
$ name=${msg%% unsuccessfully *}
$ echo ${#name} "?" ${#msg}
60 ? 60
$ echo ${msg%% successfully *}
file name
below are the scripts that i've edited based on my understanding:
#!/bin/sh
dir=/home/user/input/test.log
msg=`tail -1 $dir`
name=${msg%% Failed *}
status=Failed
if [ ${#name} -eq ${#msg} ]
then
# length of string is same as original message
# ie replace matched nothing - assume success string
# status=success
name=${msg%% successfully *}
status=Success
fi
datetime=${msg##*ran on } # remove "ran on " and all proceeding
datetime=${datetime%% SST *} # remove " SST " and all following
time=${datetime##* } # remove last space and all proceeding
date=${datetime% *} # remove last space and all following
echo "$msg"
echo "$name"
echo "$status"
the script output:
if success:
report_name successfully ran on Tue Jul 11 23:15:00 SST 2010.
report_name
Success
00:15:00
if failed:
ERROR: report_name is Failed on Tue Jul 11 23:15:00 SST 2010. ErrorCode : 500
ERROR: report_name is
Failed
00:15:00
BUT the output for name should be only "report_name" instead of "ERROR: report_name is" if failed
This is back to my point that using a word somewhere down the string as a delimeter is not going to return what you want.
Are you able to show us several lines from the file you are looking at.
Also several of the lines you are showing actually do nothing to help the output:
Code:
datetime=${msg##*ran on } # remove "ran on " and all proceeding
datetime=${datetime%% SST *} # remove " SST " and all following
time=${datetime##* } # remove last space and all proceeding
date=${datetime% *} # remove last space and all following
None of these are output anywhere so not sure why you bothered?
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.