LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
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 09-19-2011, 02:14 AM   #1
satishchahar
LQ Newbie
 
Registered: Sep 2011
Posts: 17

Rep: Reputation: Disabled
How to compare negative and decimal numbers


a=-3.123
b=4.2

if [ $a > $b ]; then
echo "It's OK"
else
echo "It's not OK"
fi

It is showing me wrong result. Please suggest how can I compare negative and decimal numbers all together.
 
Old 09-19-2011, 03:17 AM   #2
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
The shell cannot do floating point arithmetic. You have to use an external command, like bc. Example:
Code:
a=-3.123
b=4.2

if [[ $(echo "$a > $b" | bc) -eq 1 ]]
then
  echo "It's OK"
else
  echo "It's not OK"
fi
 
Old 09-19-2011, 03:18 AM   #3
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

bc comes to mind. Here's one way:
Code:
#!/bin/sh

a="-3.123"
b="4.2"

case $(echo "a=$a ;b=$b ;r=-1 ;if(a==b)r=0 ;if(a>b)r=1 ;r" | bc)
in
  0) echo $a and $b are equal ;;
  1) echo $a is bigger then $b ;;
  *) echo $a is less then $b ;;
esac
- Linux / Unix Command: bc
- bc -- The Linux Command-line Calculator

Hope this helps.
 
Old 09-19-2011, 08:14 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Not to mention that you got the shell test wrong anyway. ">" is a string comparison operator. It compares the ascii values of the two sides. You need to use options like "-gt" when comparing integer values.

Code:
if [ "$a" -gt "$b" ]; then
http://www.tldp.org/LDP/abs/html/comparison-ops.html

Don't forget to quote your variables too. Although it isn't a problem with integer inputs like this, it would break if you used a string with a space in it.

However, if you're using bash and portability isn't an issue, it's recommended to use ((..)) instead when working with numbers, and [[..]] when you have strings, filenames, or complex tests.

http://mywiki.wooledge.org/ArithmeticExpression
http://mywiki.wooledge.org/BashFAQ/031

And more on floating point arithmetic here:
http://mywiki.wooledge.org/BashFAQ/022


PS: Please use [code][/code] tags around your code, to preserve formatting and to improve readability.

Last edited by David the H.; 09-19-2011 at 08:18 AM. Reason: added one link and substituted another
 
Old 09-19-2011, 08:24 AM   #5
H_TeXMeX_H
LQ Guru
 
Registered: Oct 2005
Location: $RANDOM
Distribution: slackware64
Posts: 12,928
Blog Entries: 2

Rep: Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301Reputation: 1301
You can also use awk:

Code:
bash-4.1$ a=-3.123
bash-4.1$ b=4.2
bash-4.1$ echo $a $b | awk '{ if ($1 > $2) print "ok"; else print "not ok"}'
not ok
bash-4.1$ echo $b $a | awk '{ if ($1 > $2) print "ok"; else print "not ok"}'
ok
 
Old 09-20-2011, 03:29 AM   #6
satishchahar
LQ Newbie
 
Registered: Sep 2011
Posts: 17

Original Poster
Rep: Reputation: Disabled
A file is having last field of each line as a number (eg. -3.213 or 2.1 or whatever else) and I want to compare this number with 4.2 which I am now able to compare using the above commands.

But Can I delete the line instantly (in place) from this file which is having number less than 4.2. How? Please suggest.
 
Old 09-20-2011, 03:46 AM   #7
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,
Quote:
Originally Posted by satishchahar View Post
A file is having last field of each line as a number (eg. -3.213 or 2.1 or whatever else) and I want to compare this number with 4.2 which I am now able to compare using the above commands.

But Can I delete the line instantly (in place) from this file which is having number less than 4.2. How? Please suggest.
Too my knowledge you cannot do this directly (in place), but using a temporary file it will work:
Code:
$ cat infile
just a sample line -5
just a sample line 4.1
Just a sample line 4.2
just a sample line 4.3

$ awk '{ if ($NF < 4.2 ) next ; else print }' infile > tempfile

$ cat tempfile
just a sample line 4.2
just a sample line 4.3

$ mv tempfile infile
Hope this helps.
 
Old 09-20-2011, 03:49 AM   #8
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Yes, GNU awk can do that:
Code:
awk '{ if ($NF < 4.2 ) next ; else print > FILENAME }' infile
 
1 members found this post helpful.
Old 09-20-2011, 04:01 AM   #9
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
@colucix: I stand corrected (and I learned something!) Thanks.
 
Old 09-20-2011, 04:11 AM   #10
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
You're welcome! Just a little add-on. I remember an old post by radulov (the greatest awk master here at LQ) suggesting another method that probably works even with non-GNU awk implementation (I cannot test it right now). It was:
Code:
( rm infile && awk '{ if ($NF < 4.2 ) next ; else print }' > infile; ) < infile
this one passes the content of infile to a subshell as standard input, so that the standard output can be safely redirected to the file itself. A bit more tricky, but maybe useful in some cases.
 
Old 09-20-2011, 06:01 AM   #11
satishchahar
LQ Newbie
 
Registered: Sep 2011
Posts: 17

Original Poster
Rep: Reputation: Disabled
Last query:

If last field is like below, then how to compare and delete line:

$ cat infile
just a sample line with number=-5
just a sample line with number=4.1
Just a sample line with number=4.2
just a sample line with number=4.3
 
Old 09-20-2011, 06:18 AM   #12
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

You can set a different, or multiple record separators:

awk -F"=| " '{ if ($NF < 4.2 ) next ; else print }' infile

The -F"=| " part sets 2 separators a = and a space.

Code:
$ awk -F"=| " '{ if ($NF < 4.2 ) next ; else print }' infile
Just a sample line number=4.2
just a sample line number=4.3
Hope this helps.
 
Old 09-20-2011, 01:51 PM   #13
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
When posting sample data for testing parsers that may be sensitive to formatting, it is a good idea to post the data in [CODE][/CODE] tags to preserve the formatting.
--- rod.
 
Old 09-21-2011, 05:20 AM   #14
satishchahar
LQ Newbie
 
Registered: Sep 2011
Posts: 17

Original Poster
Rep: Reputation: Disabled
Hi druuna

Your Idea worked for me to get the data exactly but when I am sending the output the command to EMAIL, I am getting the output in one line

Quote:
$ awk -F"=| " '{ if ($NF < 4.2 ) next ; else print }' infile | mail -s "postgrep" abc@xyz.local
Below is the output I am getting in my mail client:

Quote:
Just a sample line number=4.2 just a sample line number=4.3
 
Old 09-21-2011, 07:42 AM   #15
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Is the above exactly how you did this? I'm asking because on my side it works as expected (I get a mail with separated lines). The output separators that awk uses aren't changed and lines should be put one below the other, not one after the other.

What is the output of the following (bold) commands:
Code:
$ file infile

$ awk -F"=| " '{ if ($NF < 4.2 ) next ; else print }' infile > outfile

$ file outfile
 
  


Reply



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
How to add decimal numbers in Linux MinuPriya Linux - Newbie 5 08-11-2010 12:31 AM
How can i subtract two non-real (aka decimal'd) numbers via bash onesikgypo Programming 3 04-28-2010 11:55 AM
Compare Decimal Values rbautch Linux - General 10 04-22-2008 04:11 AM
Decimal numbers in bash script variables? Massif Programming 3 11-07-2005 09:01 PM
How to use decimal numbers in in shell scripts a1ex_007 Programming 6 03-11-2005 09:05 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:47 PM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration