1

Qestion First: I need to regex to match 111 or 111. or 111.111 (just aritrarty numbers) for a DocumentFilter. I need the user to be able to input 111. with a decimal and nothing afterwards. Can't seem to get it right.

All the Regexes I find all match just all decimal numbers i.e.

12343.5565
32.434
32

Like this regex

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

Problem is, I need the regex for a DocumentFilter so the input can only be numbers with/without a decimal point. But the catch is it also needs to match

1223.

So the user can input the decimal into the text field. So basically I need to regex to match

11111         // all integer
11111.        // all integers with one decimal point and nothing after
11111.1111    // all decimal numbers

The pattern I have so far is the one above. Here is a test program (For Java users)

The patter can be input in the this line

 Pattern regEx = Pattern.compile("^[0-9]*(\\.)?[0-9]+$");

If the regex fits the bill, then you will be able to input 111 or 111. or 111.111.

Run it :)

import java.awt.GridBagLayout;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.text.*;

public class DocumentFilterRegex {

    JTextField field = new JTextField(20);

    public DocumentFilterRegex() {

        ((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {
            Pattern regEx = Pattern.compile("^[0-9]*(\\.)?[0-9]+$");

            @Override
            public void insertString(DocumentFilter.FilterBypass fb, int off, String str, AttributeSet attr)
                    throws BadLocationException {
                Matcher matcher = regEx.matcher(str);
                if (!matcher.matches()) {
                    return;
                }
                super.insertString(fb, off, str, attr);
            }

            @Override
            public void replace(DocumentFilter.FilterBypass fb, int off, int len, String str, AttributeSet attr)
                    throws BadLocationException {
                Matcher matcher = regEx.matcher(str);
                if (!matcher.matches()) {
                    return;
                }
                super.replace(fb, off, len, str, attr);
            }
        });

        JFrame frame = new JFrame("Regex Filter");
        frame.setLayout(new GridBagLayout());
        frame.add(field);
        frame.setSize(300, 150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new DocumentFilterRegex();
            }
        });
    }
}

EDIT:

My original assumption that the str passed to the methods were the entire document String, so I was confused about why the answers didn't work. I realized it was only the attempted inserted portion of the String that is passed.

That said, the answers work perfect, if you get the entire document String from the FilterBypass and check the regex against the entire document String. Something like

@Override
public void insertString(DocumentFilter.FilterBypass fb, int off, String str, AttributeSet attr)
        throws BadLocationException {

    String text = fb.getDocument().getText(0, fb.getDocument().getLength() - 1);
    Matcher matcher = regEx.matcher(text);
    if (!matcher.matches()) {
        return;
    }
    super.insertString(fb, off, str, attr);
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720

2 Answers2

2

The following regex might work for you:

^[0-9]+[.]?[0-9]{0,}$

The quantifier {0,} would match zero or more digits.

devnull
  • 118,548
  • 33
  • 236
  • 227
  • I've tried it and it doesn't allow the `.` input. I'm not great with regex, but I'm guessing maybe it doesn't match `1111.` Again I have no clue – Paul Samsotha Feb 11 '14 at 14:39
  • @peeskillet Since you're using `.matches` remove the anchors at the beginning and the end. – devnull Feb 11 '14 at 14:57
  • +1 Thanks for the help. I'm pretty sure the regex is good. I'm going to look elsewhere for the problem – Paul Samsotha Feb 11 '14 at 15:07
2

I would use the regex

^\d+\.?\d*$

Explanation and demonstration here: http://regex101.com/r/iM3nX5

Make sure you double-escape the escape sequences, like this:

Pattern regEx = Pattern.compile("^\\d+\\.?\\d*$");
The Guy with The Hat
  • 10,836
  • 8
  • 57
  • 75
  • This would allow the number to start with zeroes, but beyond that it's the best solution. Edit: if you don't want it to start with zeroes, you could change it to: `"^([1-9]\d*|0)\.?\d*$"` – Bart Enkelaar Feb 11 '14 at 14:41
  • For my `DocumentFilter` the user should be able to input `1111.` but it's not allowing the `.` after `1111`. I don't know if it's a problem with the regex or something else. But the `DocumentFilter` what it does is if it mathes the pattern, it will allow input of the last typed character. If not then it wont allow the last input. The last input being the `.` in my case. If you have Java you can run the above app. – Paul Samsotha Feb 11 '14 at 14:50
  • @peeskillet My regex and the regex given by devnull both work, so the problem is in the implementation. – The Guy with The Hat Feb 11 '14 at 14:55
  • +1 Thanks for the help. I'm pretty sure the regex is good. I'm going to look elsewhere for the problem – Paul Samsotha Feb 11 '14 at 15:07