Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'd like to filter through a text file and only print the lines where each column is a valid floating point number. For example:

3 6 2 -4.2 21.2 
3 x 4.2 21.2 
3 2 2.2.2

Only the first line would pass as x, nor 2.2.2 are valid floats. I can write a python script that simply .splits() and runs a try/except block over each part, but this is slow for larger files. The input file has an unknown variable length number of columns and no scientific notation will be used. Is there an awk solution?

share|improve this question
awk '
    # skip any obvious stuff
    /[^0-9. -]/ {next}
        # test each field for a number
        for (i=1; i<=NF; i++) 
            if ($i + 0 != $i)

This will break for valid numbers in scientific notation: 1.2e1 == 12

share|improve this answer
One can easily add e in the regular expression [^0-9. -e]. The test will then only fail when there are only e's in the line. – Bernhard Jun 23 '14 at 7:16
Be careful with bracket expressions: [0-9. -e] will match any character from space (ascii 32) to e (ascii 101). You want [^0-9. e-]: to match a literal hyphen, it needs to be either the first or the last character, otherwise it defines a range of chars. (gnu.org/software/gnulib/manual/html_node/…) – glenn jackman Jun 23 '14 at 13:05
Ah, that is smart, thanks for correcting. – Bernhard Jun 23 '14 at 15:18

Try something like this:

$ cat data.txt 
3 6 2 -4.2 21.2 
3 x 4.2 21.2 
3 2 2.2.2

$ awk '/^\s*(-?[0-9]+(\.[0-9]*)?\s+)+\s*$/ { print }' < data.txt 
3 6 2 -4.2 21.2 
share|improve this answer
PS: you asked for awk. Should be using grep instead... – Axel Oct 22 '12 at 20:40

based on the conditions you state regex might be a possibility. I was able to get the following GNU awk script to work on RHEL.

 awk '{for (i=1; i<=NF; ++i) {if ($i !~ /^[-]?[[:digit:]]+(\.[[:digit:]]+)?$/) break;if (i == NF)print($0)}}' file.txt
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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