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.. |
The command to extract the substring is valid:
Code:
jlinkels@jlinkels-lt:~$ msg="hello world" Try this to test: Code:
jlinkels@jlinkels-lt:~$ which sh Code:
bash test.sh Code:
bash -x test.sh jlinkels |
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 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 |
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" |
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 |
thanks grails,
but what if the file name has several words, for example: daily product tested that include the space?? |
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 *} |
Bash arrays can be useful
Code:
#!/bin/bash |
@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 |
Dear tedy2808,
Please try to use codes in shell scripts/commands/outputs in the thread. It makes the thread a lot more readable. |
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? |
Ok I'll try and explain (numbered for ease of reference):
Code:
1 name=${msg%% unsuccesfully *} 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" |
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 |
All times are GMT -5. The time now is 07:57 PM. |