LinuxQuestions.org
Register a domain and help support LQ
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 07-16-2009, 01:36 PM   #1
billywayne
LQ Newbie
 
Registered: May 2009
Posts: 15

Rep: Reputation: 0
Question extracting floating numbers from variable using bash's builtin string chopping


Hi. I'm wanting to use bash3 to chop up some strings! :-)

Here's the string I want to chop:

Code:
C9-1.4-1.6
, which I'm assigning to a variable that I'm naming $window.

I'm wanting to chop out the 1.4 and the 1.6. The 1.6 is simple enough with something like

Code:
echo "${window##*-}"
which, of course, chops off the beginning of the string until the final -.

What I'm having trouble with is getting the 1.4 out of there. I can do it with a simple

Code:
echo "${window:3:3}"
to pull out the substring, but the thing is, sometimes the window I'm manipulating is something like

Code:
C10-1.4-1.6
, in which case the above will give me

Code:
-1.
which obviously isn't what I'm looking for.

So, to summarize, I have a string that contains two 2-digit floating point numbers, separated off by dashes(-), and I want to extract these and only these strings.

Any help appreciated!


billywayne
 
Old 07-16-2009, 01:57 PM   #2
nc3b
Member
 
Registered: Aug 2005
Posts: 330

Rep: Reputation: 32
Hello. Here is one solution (surely not the only one and surely not the best):

Code:
var='C9-1.4-1.6'
var="${var#*-}"
echo "${var%%-*}"
This will give you 1.4, but it will do so in two steps. Waiting to see if there is a nicer way. Hope this helps though.


Cheers
 
Old 07-16-2009, 02:00 PM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946
echo "${window#*-}"

If you use only one hashmark, it stops at the first match.

Edit: After seeing the above post, I think I misunderstood the question. You want to extract only the middle number? I don't think that's generally doable in one step through parameter substitution (except by the 3:3 column matching you already know about). You have to use multiple steps as above, or an external tool like grep, sed, or awk for that.

Last edited by David the H.; 07-16-2009 at 02:05 PM.
 
Old 07-16-2009, 03:02 PM   #4
billywayne
LQ Newbie
 
Registered: May 2009
Posts: 15

Original Poster
Rep: Reputation: 0
OK. Thanks for the replies.

I was hoping for something like a

Code:
echo ${var#*-%-*}
but d'oh well. thanks, again.


billywayne
 
Old 07-16-2009, 03:26 PM   #5
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,396

Rep: Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814
Here's a way that technically extracts the everything in one step, although you can't echo it in the same command.

Code:
window='C9-1.4-1.6'
IFS=- read one two three <<<"$window"
echo "one = $one, two = $two, three = $three"
EDIT:
thought of something like ${var#*-%-*}, kind of ugly though
Code:
shopt -s extglob # requires extended globs
echo ${var//@(+([^-])-|-+([^-]))/}

Last edited by ntubski; 07-16-2009 at 03:41 PM. Reason: thought of something else
 
Old 07-16-2009, 08:21 PM   #6
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 240Reputation: 240Reputation: 240
Code:
# IFS="-"
# a="C9-1.4-1.6"
set -- $a
# echo $1
C9
 
Old 07-17-2009, 03:42 AM   #7
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946
Quote:
Originally Posted by ntubski View Post
thought of something like ${var#*-%-*}, kind of ugly though
Code:
shopt -s extglob # requires extended globs
echo ${var//@(+([^-])-|-+([^-]))/}
Actually, that's rather neat. I should've known that there would be a shell option for things like this (note to self: read up on shopt). Don't forget to turn it off again when you're finished with it (shopt -u extglob).

Quote:
Originally Posted by ghostdog74
Code:
# IFS="-"
# a="C9-1.4-1.6"
set -- $a
# echo $1
C9
This is also pretty cool, but you should be aware that it also unsets all of the previous positional parameters, as well as replacing the first three. This could have rather undesirable effects inside a script if you're not careful.

In the end though, it's seems obvious that there's no way to do it in a single line. It's going to take two or more commands to extract the middle portion no matter what you try. I think ntubski's solution above is the cleanest one, personally, if you really need it all done in one operation. Otherwise, the simplest solution is probably just to step it through two iterations of variable expansion.
Code:
var="C9-1.4-1.6"
var="${var#*-}"
echo "${var%-*}"

Last edited by David the H.; 07-17-2009 at 03:48 AM.
 
Old 07-17-2009, 04:09 AM   #8
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 240Reputation: 240Reputation: 240
Quote:
Originally Posted by David the H. View Post
This is also pretty cool, but you should be aware that it also unsets all of the previous positional parameters, as well as replacing the first three. This could have rather undesirable effects inside a script if you're not careful.
just unset it back after every usage
Code:
unset IFS
 
Old 07-17-2009, 04:27 AM   #9
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946Reputation: 1946
Quote:
Originally Posted by ghostdog74 View Post
just unset it back after every usage
Code:
unset IFS
You missed my point. It's not IFS that concerns me, but the $1, $2, etc. positional parameters. If any subsequent code in your script relies on the original input from higher-numbered positionals (there's a line that uses $4, for example), then using your line above will break it, because "set --" will unset them. And of course the original values of $1, $2, and $3 are all overwritten.

It's not necessarily a fatal flaw, but it could cause problems if you're not careful.
 
Old 07-17-2009, 05:03 AM   #10
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 240Reputation: 240Reputation: 240
Quote:
Originally Posted by David the H. View Post
You missed my point.
an example might be more clear in what you are trying to explain. i am an english idiot.
 
Old 07-17-2009, 06:32 AM   #11
vonbiber
Member
 
Registered: Apr 2009
Distribution: slackware
Posts: 296

Rep: Reputation: 50
Quote:
Originally Posted by billywayne View Post
Here's the string I want to chop:

Code:
C9-1.4-1.6
, which I'm assigning to a variable that I'm naming $window.

I'm wanting to chop out the 1.4 and the 1.6. simple

I have a string that contains two 2-digit floating point numbers, separated off by dashes(-), and I want to extract these and only these strings.
why don't you just use the 'cut' command?

str1=$(echo $window | cut -d'-' -f1)
str2=$(echo $window | cut -d'-' -f2)
str3=$(echo $window | cut -d'-' -f3)
 
Old 07-17-2009, 06:52 AM   #12
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,695
Blog Entries: 5

Rep: Reputation: 240Reputation: 240Reputation: 240
Quote:
Originally Posted by vonbiber View Post
why don't you just use the 'cut' command?
because its not necessary to call it 3 times on 1 variable.
 
Old 07-17-2009, 08:35 AM   #13
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,531
Blog Entries: 27

Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
Hello

Just to add another parsing technique (ntubski's ${var//@(+([^-])-|-+([^-]))/} is already a magnificent solution), how about
Code:
$ a="C9-1.4-1.6"
$ IFS='-'
$ array=($a)
$ unset IFS
$ echo ${array[1]} ${array[2]}
1.4 1.6
Best

Charles
 
Old 07-17-2009, 11:43 AM   #14
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,396

Rep: Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814Reputation: 814
Quote:
Originally Posted by David the H. View Post
Don't forget to turn it off again when you're finished with it (shopt -u extglob).
Or you could just have it on throughout the script.

Quote:
Originally Posted by ghostdog
just unset it back after every usage
Code:
unset IFS
As far as I know, unset'ing IFS won't restore the previous value.
 
Old 07-17-2009, 12:14 PM   #15
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,531
Blog Entries: 27

Rep: Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176Reputation: 1176
Thanks ntubski
Quote:
Originally Posted by ntubski View Post
Or you could just have it [shopt -u extglob] on throughout the script
I set it in the shell initialisation; why not?
Quote:
Originally Posted by ntubski View Post
As far as I know, unset'ing IFS won't restore the previous value.
I doesn't; that will teach me not to unquestioningly accept what is posted here! My own scripting idiom is
Code:
oIFS="$IFS"
IFS="<whatever>"
<commands>
IFS="$oIFS"
Best

Charles
 
  


Reply

Tags
bash, strings


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
chopping away unwanted parts in string C's Brother Programming 3 11-02-2008 07:56 AM
LXer: The trouble with rounding floating point numbers LXer Syndicated Linux News 0 08-12-2006 01:54 PM
IEEE 754 floating point numbers dmail Programming 3 02-05-2006 05:10 AM
modulo of 2 floating point numbers? jenna_h Programming 6 09-24-2004 09:39 AM
floating point numbers in java spyghost Programming 8 09-06-2003 06:21 PM


All times are GMT -5. The time now is 12:22 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