Regex for DocumentFilter to match all decimal number but also number with just a decimal at the end
Asked Answered
S

2

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);
}
Steere answered 11/2, 2014 at 14:27 Comment(2)
Do you have a question here?Millinery
I need a regex to match 111 or 111. or 111.111Steere
M
2

The following regex might work for you:

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

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

Millinery answered 11/2, 2014 at 14:35 Comment(3)
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 clueSteere
@peeskillet Since you're using .matches remove the anchors at the beginning and the end.Millinery
+1 Thanks for the help. I'm pretty sure the regex is good. I'm going to look elsewhere for the problemSteere
C
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*$");
Chiu answered 11/2, 2014 at 14:39 Comment(4)
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*$"Globulin
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.Steere
@peeskillet My regex and the regex given by devnull both work, so the problem is in the implementation.Chiu
+1 Thanks for the help. I'm pretty sure the regex is good. I'm going to look elsewhere for the problemSteere

© 2022 - 2024 — McMap. All rights reserved.