LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-14-2012, 02:26 PM   #1
saeedamer
LQ Newbie
 
Registered: Feb 2011
Posts: 25

Rep: Reputation: 0
substr using start-end position?


Hi there

I am not shell scripting expert. I want to extract a substring out of a string starting at a particular position and ending at particular position. The string is a directory path and I want to extract a certain part of this directory path (as substring).

So for example if I have following directory:

Code:
/su01/app/oracle/admin/testdb/bdump
I want to extract "testdb" out of the above path. The "/su01/app/oracle/admin/" part of the path will always be same. The "testdb" will change and "/bdump" will always be the same.

This is how I am trying to do this:

Code:
for lin in `find /su01 -name "bdump" -print 2>/dev/null `
  do
     echo $lin
     st=`echo $lin | awk '{print match($0, "admin")}'`
     en=`echo $lin | awk '{print match($0, "bdump")}'`
     db=`echo $lin | nawk '{print substr($lin,$st+6,$en-1)}'`
     echo $db
     echo $st
     echo $en
  done
Looks like substr will not allow me to specify the START position and END position. Can this be done in any other way?

Please advise!
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 03-14-2012, 02:49 PM   #2
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Actually the substr function in awk requires the string, the start and the length of the string, not the ending position, hence you have to compute the length of the string by subtraction. Anyway, why not using the dirname and basename commands? Example:
Code:
$ basename `dirname /su01/app/oracle/admin/testdb/bdump`
testdb
Hope this helps.
 
2 members found this post helpful.
Old 03-14-2012, 03:33 PM   #3
whizje
Member
 
Registered: Sep 2008
Location: The Netherlands
Distribution: Slackware64 current
Posts: 583

Rep: Reputation: 129Reputation: 129
${string#substring} removes shortest substring from front of string
${string%%substring} removes longest substring from end of string
Code:
str='/su01/app/oracle/admin/testdb/bdump';str=${str#*admin/};echo ${str%%/*}
testd

Last edited by whizje; 03-14-2012 at 03:34 PM.
 
1 members found this post helpful.
Old 03-14-2012, 03:59 PM   #4
danielbmartin
Senior Member
 
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 1,136

Rep: Reputation: 299Reputation: 299Reputation: 299
There are lots of ways to do this.
Here is another: reverse, cut, reverse.
Code:
echo "/su01/app/oracle/admin/testdb/bdump" |rev |cut -d/ -f2 |rev
Daniel B. Martin
 
1 members found this post helpful.
Old 03-14-2012, 10:09 PM   #5
adixon
Member
 
Registered: Oct 2010
Posts: 34

Rep: Reputation: 3
can also change the delimiters awk uses

Code:
.
.
db=`echo $lin | awk --field-separator="/" '{print $6)}'`
echo $db
.
.
 
1 members found this post helpful.
Old 03-15-2012, 02:32 AM   #6
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,564

Rep: Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939Reputation: 1939
May I also suggest that you look at the man page for find as you could get it to return:
Code:
/su01/app/oracle/admin/testdb
 
1 members found this post helpful.
Old 03-15-2012, 05:12 AM   #7
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 13.1
Posts: 1,320

Rep: Reputation: 252Reputation: 252Reputation: 252
Quote:
Originally Posted by saeedamer View Post
Code:
for lin in `find /su01 -name "bdump" -print 2>/dev/null `
  do
     echo $lin
     st=`echo $lin | awk '{print match($0, "admin")}'`
     en=`echo $lin | awk '{print match($0, "bdump")}'`
     db=`echo $lin | nawk '{print substr($lin,$st+6,$en-1)}'`
     echo $db
     echo $st
     echo $en
  done
Besides all the suggestions to get the result, I would like to mention for the above sequence: the environment variables won’t be known inside the awk script. It’s either necessary to use proper quoting or make them known inside awk by the -v option:
Code:
db=`echo $lin | awk -v st=$st -v en=$en '{print substr($0,st+6,en-st-7)}'`
And then it could be put in one statement to read:
Code:
db=`echo $lin | awk '{st=match($0, "admin"); en=match($0, "bdump"); print substr($0,st+6,en-st-7)}'`
 
2 members found this post helpful.
Old 03-15-2012, 06:40 AM   #8
saeedamer
LQ Newbie
 
Registered: Feb 2011
Posts: 25

Original Poster
Rep: Reputation: 0
Thank you so so much everyone!!!
 
Old 03-15-2012, 07:37 AM   #9
Reuti
Senior Member
 
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 13.1
Posts: 1,320

Rep: Reputation: 252Reputation: 252Reputation: 252
NB: If you expect the results only in /su01/app/oracle/admin, it would be good to use it as start directory in the find command as it will return faster (assuming there is more in /su01 besides the files in question). Then find can be tuned to output “testdb/bdump”. It’s a matter of taste, whether to remove the leading part like with Grails suggestion, or the trailing one.

It’s a pitty, that -printf will only change the output, but not the string used for {} in -exec, so you need xargs in addition. Maybe -setf would be an RFE.
 
1 members found this post helpful.
Old 03-15-2012, 02:39 PM   #10
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
See here for lots of bash string manipulation techniques:

http://mywiki.wooledge.org/BashFAQ/100

One of the best options in this situation is to load the path into an array, splitting the string by "/", of course.

Code:
$ IFS='/' read -a path <<<'/su01/app/oracle/admin/testdb/bdump'

$ echo "${path[1]}" "${path[3]}" "${path[5]}"
su01 oracle testdb

(P.S. If you're wondering why the array appears to not be zero-based, note that if IFS is set to a non-space value, the empty string in front of a leading delimiter is read as element "0".)
 
1 members found this post helpful.
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Vim - string replacement from current position to end of file armandino Linux - General 1 01-24-2011 03:12 PM
awk from end of string -3 position comparison dazdaz Linux - Software 4 10-04-2010 10:31 AM
BASH Sort list by end of line to x position in each line? SilversleevesX Programming 14 08-19-2010 08:30 PM
[Need Audio Program to Remember Start Position] sharpdust Linux - Software 0 10-26-2007 11:31 AM


All times are GMT -5. The time now is 10:46 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration