1

I'm using a regular expression to match floating point numbers:

for f in $float_numbers ; do
    if [ $f =~ "[0-9]*\.?[0-9]*" ] ; then
        echo "****f is $f ****"
    fi
done

where $float_numbers contains floating point numbers like 1.2, 10.5, 4.0, etc.

But nothing matches.

  • When asking a question, you should also include the error messages you are getting. – terdon Dec 5 '16 at 10:20
1

terdon has corrected your syntax, but your regular expression is wrong:

[0-9]*\.?[0-9]*

All quantifiers there (*, ?) mean all parts of the expression are optional. That means your regex will match every string, including strings that are empty and strings that have no digits.

To match a float number, you need to match at least one digit.

([0-9]+\.?[0-9]*)|([0-9]*\.[0-9]+)

That matches some digits with an optional decimal point and optional digits (example: 3.14 or 42), or some optional digits but a required decimal point and required digits (example: .1234 or 3.14).

It is not anchored, so the string "PI starts with 3.14 and continues" will match.

Testing:

for n in "" "no digits" 42 3.14 "this is .1234 go"; do 
    if [[ $n =~ ([0-9]+\.?[0-9]*)|([0-9]*\.[0-9]+) ]]; then
        echo "yes -- $n -- ${BASH_REMATCH[0]}"
    fi
done
yes -- 42 -- 42
yes -- 3.14 -- 3.14
yes -- this is .1234 go -- .1234
1

First of all, your code has a syntax error and should complain about:

bash: [: =~: binary operator expected

Assuming you are running bash, but based on your code, you probably are. So, in bash, the =~ only works inside [[ ]], not [ ]. You also shouldn't quote your regular expression. You are looking for something like this:

$ for f in $float_numbers; do 
    [[ $f =~ [0-9]*\.?[0-9]* ]] && echo $f
  done
1.2
10.5
4.0

However, as Glenn very correctly pointed out, your regex is wrong in the first place.

0

I suggest you to use this txt2re to build regex that match what you want.

For you script:

for f in $float_numbers ; do
    if [[ $f =~ ^[+-]?[0-9]+\.?[0-9]*$ ]]; then
        echo "****f is $f ****"
    fi
done

Rexeplanation:

^       # Match start of string
[-+]?   # Match a leading + or - (optional)
[0-9]+  # Match one or more digit
\.?     # Match a literal . (optional, escaped)
[0-9]*  # Match zero or more digits
$       # Match the end of the string

And this is perl script generated by the previous site that match a float numbers

#!/usr/bin/perl

# URL that generated this code:
# http://txt2re.com/index.php3?s=100.3&1

$txt='100.3';

$re1='([+-]?\\d*\\.\\d+)';  # Float 1

$re=$re1;
if ($txt =~ m/$re/is)
{
    $float1=$1;
    print "($float1) \n";
}

#-----
# Paste the code into a new perl file. Then in Unix:
# $ perl x.pl 
#-----
  • Why would you use \\d* instead of \d? Why are you using a negative lookahead there? You are matching "1 or more digits" (\d+) and "not followed by =,-, . or more digits. I dont' understand why that helps in any way. – terdon Dec 5 '16 at 10:19
  • @terdon i totally agree with you i didn't find any reason to (?![-+0-9\\.]) – Wissam Roujoulah Dec 5 '16 at 10:34
0

A more precise regular expression for matching floats would be:

^[-+]?([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)$

This comes down to what you would consider a float. Python, for example, accepts both 5. and .5 as valid floats, and does not require a leading or trailing digit before or after the .:

>>> 5.
5.0
>>> .5
0.5

So the above regex handles these cases, and also the edge case of just . (which should not be a match).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.