Linux - Newbie This 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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
|
07-13-2010, 09:27 PM
|
#1
|
|
Member
Registered: Jul 2010
Posts: 34
Rep:
|
getting sub-string in a variable
Hi all,
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.
guide me please..
|
|
|
|
07-13-2010, 09:54 PM
|
#2
|
|
Senior Member
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Lenny/Squeeze/Wheezy/Sid
Posts: 3,801
|
The command to extract the substring is valid:
Code:
jlinkels@jlinkels-lt:~$ msg="hello world"
jlinkels@jlinkels-lt:~$ part=${msg:0:5}
jlinkels@jlinkels-lt:~$ echo $part
hello
Are you sure you are running Bash?
Try this to test:
Code:
jlinkels@jlinkels-lt:~$ which sh
/bin/sh
jlinkels@jlinkels-lt:~$ file /bin/sh
/bin/sh: symbolic link to `bash'
jlinkels@jlinkels-lt:~$
If it is not Bash, run your script:
Or even better:
to see every line of code executed and echoed.
jlinkels
|
|
|
|
07-13-2010, 11:09 PM
|
#3
|
|
Member
Registered: Mar 2009
Posts: 32
Rep:
|
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:
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.
|
|
|
|
07-14-2010, 12:15 AM
|
#4
|
|
Member
Registered: Jul 2010
Posts: 34
Original Poster
Rep:
|
set sub-string as variable
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?
#!/bin/sh
dir=/home/user/input/test.log
#cat $dir
msg=`tail -1 $dir`
sub=`echo ${msg:6:23}`
echo "$sub"
#name=${msg:0:21}
echo "$msg"
#echo "$name"
|
|
|
|
07-14-2010, 12:59 AM
|
#5
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,325
|
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:
Code:
awk 'END{print $1}' $dir
This will return the file_name
|
|
|
|
07-14-2010, 05:33 AM
|
#6
|
|
Member
Registered: Jul 2010
Posts: 34
Original Poster
Rep:
|
thanks grails,
but what if the file name has several words,
for example: daily product tested that include the space??
|
|
|
|
07-14-2010, 07:06 AM
|
#7
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,325
|
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
|
|
|
|
07-14-2010, 11:39 AM
|
#8
|
|
Member
Registered: Mar 2009
Posts: 32
Rep:
|
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
|
|
|
|
07-14-2010, 01:05 PM
|
#9
|
|
Senior Member
Registered: Aug 2003
Location: Birkenhead/Britain
Distribution: Linux From Scratch
Posts: 2,073
Rep:
|
Bash arrays can be useful
Code:
#!/bin/bash
set -e
dir=/home/user/input/test.log
msg=($(tail -1 $dir))
echo ${msg[0]} ${msg[1]} ran on ${msg[4]} ${msg[5]} ${msg[6]} ${msg[7]} ${msg[8]} ${msg[9]}
|
|
|
|
07-14-2010, 09:17 PM
|
#10
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,325
|
@Andy - I think arrays will still fail in this scenario as the user is now indicating the input file string may look like:
file name successfully ran on Mon Jul 12 23:15:00 SST 2009
Which I believe your suggestion will place "name successfully" in ${msg[1]} which would be wrong
|
|
|
|
07-14-2010, 09:47 PM
|
#11
|
|
Senior Member
Registered: May 2007
Distribution: RHEL, CentOS
Posts: 1,231
Rep:
|
Dear tedy2808,
Please try to use codes in shell scripts/commands/outputs in the thread. It makes the thread a lot more readable.
|
|
|
|
07-14-2010, 11:47 PM
|
#12
|
|
Member
Registered: Jul 2010
Posts: 34
Original Poster
Rep:
|
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
can anyone explain clearly to me?
|
|
|
|
07-15-2010, 02:26 AM
|
#13
|
|
Member
Registered: Mar 2009
Posts: 32
Rep:
|
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
|
|
|
1 members found this post helpful.
|
07-15-2010, 03:48 AM
|
#14
|
|
Member
Registered: Jul 2010
Posts: 34
Original Poster
Rep:
|
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
Last edited by tedy2808; 07-15-2010 at 09:33 PM.
|
|
|
|
07-15-2010, 04:10 AM
|
#15
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,325
|
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?
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 10:36 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|