如何在Android中使用正则表达式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10327901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:18:59  来源:igfitidea点击:

How to use regular expression in Android

androidregexandroid-edittext

提问by AndroidDev

I have a numberDecimal EditTextwhich I want to validate using a regular expression. In validation what I want is:

我有一个 numberDecimal EditText,我想使用正则表达式来验证它。在验证中,我想要的是:

  1. Before the decimal point, the maximum digit I want to enter is three and the digit should not start with zero like 2,23,342, etc.

  2. After the decimal point, the maximum digit I want to enter is one like .1, .3, .6, etc.

  1. 在小数点之前,我想输入的最大数字是 3,数字不应以零开头,如2,23,342等。

  2. 小数点后,我想进入的最大数字是一个像.1.3.6等等。

So the number that I allow the user to enter is like 2.1, 32.5, 444.8, 564.9, etc.

所以,我允许用户输入的数字一样2.132.5444.8564.9,等。

But in my code, what happens is:

但在我的代码中,会发生什么:

  1. It allows the user to enter more than a three digit number before the decimal point like 3456, 4444, 5555and after that it doesn't allow me to enter a decimal point after that.

  2. It allows me to enter 0before the decimal point as the start of the digit.

  1. 它允许用户在小数点前输入超过三位数的数字,如3456, 44445555之后不允许我输入小数点。

  2. 它允许我0在小数点之前输入作为数字的开头。

So why does this happen, is anything wrong in the regular expression I have used? If anyone knows, please help me to solve this.

那么为什么会发生这种情况,我使用的正则表达式有什么问题吗?如果有人知道,请帮我解决这个问题。

Code I have used:

我使用过的代码:

weightEditText.addTextChangedListener(new TextWatcher() 
{           
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {               
    }           
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {            
    }           
    @Override
    public void afterTextChanged(Editable s) 
    {
        Pattern mPattern = Pattern.compile("^([1-9][0-9]{0,2})?(\.[0-9]?)?$");

        Matcher matcher = mPattern.matcher(s.toString());               
        if(!matcher.find())
        {
            weightEditText.setText(); // Don't know what to place                   
        }
    }
});

回答by Ted Hopp

There's never any point in examining destalone in an InputFilter; that's what's already present in the field. Change the regular expression match to be against sourceand it would be appropriate if you only wanted to check that certain characters were accepted into the field. However, you want to check field formatting, not just filter the input on a character-by-character basis. This is much more complex.

destInputFilter; 中单独检查永远没有任何意义;这就是该领域已经存在的东西。将正则表达式匹配更改为反对source,如果您只想检查字段中是否接受了某些字符,这将是合适的。但是,您想要检查字段格式,而不仅仅是逐个字符地过滤输入。这要复杂得多。

Every time the user makes a change to the contents of tempEditText, the system calls your filter's filtermethod beforethe change is actually made. It passes the current field contents and the proposed change (which can be insert/append, delete, or replace). The change is represented by a source CharSequence source(the characters—if any—to be added to the field), range start and end indexes within the source (the range is not necessarily all of source), a Spanned dest(the current field contents before the change) and range dstart and dend indexes within destthat are proposed to be replaced by the indicated sourcerange.

每次用户对 的内容进行更改时tempEditText,系统都会实际进行更改之前调用过滤器的filter方法。它传递当前字段内容和提议的更改(可以是插入/追加、删除或替换)。更改由源(要添加到字段的字符(如果有的话))、源内的范围开始和结束索引(范围不一定是 的全部)、a (更改前的当前字段内容)表示和范围内的 dstart 和 dend 索引建议由指示的范围替换。CharSequence sourcesourceSpanned destdestsource

The job of filteris to modify the change (if necessary) and return a CharSequenceto use (in its entirety) in place of source(or nullto go ahead and use source). Rather than checking destas you are now doing, you will need to check whether the change will result in an acceptable field. To do this, you will need more complex logic. (Note, in particular, that the new character(s) may be intended for insert somewhere other than at the end; also, filterwill be called when the user is deleting characters as well as adding them.)

的工作filter是修改更改(如有必要)并返回CharSequence使用(全部)代替source(或null继续使用source)。dest您需要检查更改是否会导致可接受的字段,而不是像现在这样检查。为此,您将需要更复杂的逻辑。(特别注意,新字符可能用于插入到末尾以外的其他地方;此外,filter当用户删除和添加字符时也会调用。)

It may be easier to implement a TextWatcher. In it's beforeTextChangedmethod, you can record the current contents and in it's afterTextChangedmethod, you can check (using a regular expression) whether the contents are acceptable and, if not, restore the before-the-change contents. (Make sure, though, that the text before the change was acceptable. If it isn't, substitute something acceptable—like clearing the field. Otherwise your code will go into an infinite loop because the TextWatcheris going to be invoked again when you correct the field contents.)

实现一个TextWatcher. 在it'sbeforeTextChanged方法中,可以记录当前的内容,在it'safterTextChanged方法中,可以检查(使用正则表达式)内容是否可以接受,如果不能,则恢复更改前的内容。(但是,请确保更改前的文本是可接受的。如果不是,请替换可接受的内容 - 例如清除字段。否则您的代码将进入无限循环,因为TextWatcher在您更正时将再次调用字段内容。)

You also have an error in your regular expression: it allows a leading zero. Here's an improved version that fixes this problem (and removes one set of unnecessary parentheses):

您的正则表达式中也有一个错误:它允许前导零。这是修复此问题的改进版本(并删除了一组不必要的括号):

"^([1-9][0-9]{0,2})?(\.[0-9]?)?$"

(As an aside: you can use \\dinstead of [0-9].)

(顺便说一句:您可以使用\\d代替[0-9]。)

EDIT

编辑

Here's my edit of your edit:

这是我对您的编辑的编辑:

weightEditText.addTextChangedListener(new TextWatcher() 
{           
    private static final Pattern sPattern
        = Pattern.compile("^([1-9][0-9]{0,2})?(\.[0-9]?)?$");

    private CharSequence mText;

    private boolean isValid(CharSequence s) {
        return sPattern.matcher(s).matches();
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count){
    }           

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after){
        mText = isValid(s) ? new CharSequence(s) : "";
    }           

    @Override
    public void afterTextChanged(Editable s) 
    {
        if (!isValid(s))
        {
            weightEditText.setText(mText);
        }
        mText = null;
    }
});

回答by Serg Vorontsov

Maybe my implementation will help anyone:

也许我的实现会帮助任何人:

    etRepeaterCallsign.addTextChangedListener(new TextWatcher() {
        private final Pattern sPattern
                = Pattern.compile("^([A-Z]{0,2})?(\d)?([A-Z-]{0,5})"); // ^([1-9][0-9]{0,2})?(\.[0-9]?)?$

        private CharSequence mText;

        private boolean isValid(CharSequence s) {
            return sPattern.matcher(s).matches();
        }

        @Override
        public void beforeTextChanged(CharSequence r, int start, int count,
                                      int after) {
            mText = r.toString();
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            bIsEdit = true;
        }
        @Override
        public void afterTextChanged(Editable s) {
            etRepeaterCallsign.removeTextChangedListener(this);

            int iCursorPosition = etRepeaterCallsign.getSelectionStart();
            etRepeaterCallsign.setText("");
            if (isValid(s))
                etRepeaterCallsign.append(s);
            else
                etRepeaterCallsign.append(mText);

            etRepeaterCallsign.setSelection(iCursorPosition);

            etRepeaterCallsign.addTextChangedListener(this);

        }
    });

回答by assylias

You could just parse the number and check that it is < 1000 and that 10*number is an integer while num is not. It would probably be more readable too.

您可以解析数字并检查它是否 < 1000 并且 10*number 是一个整数而 num 不是。它也可能更具可读性。

回答by npinti

You could try something like this: ^[1-9][0-9]{0,2}(\\.\\d)?$. This should match any number which does not start with 0 (^[1-9]) and is followed by at most two numbers ([0-9]{0,2}). The regex also allows for an optional decimal value ((\\.\\d)?$).

你可以尝试这样的事:^[1-9][0-9]{0,2}(\\.\\d)?$。这应该匹配任何不以 0 ( ^[1-9])开头且后跟最多两个数字 ( [0-9]{0,2}) 的数字。正则表达式还允许使用可选的十进制值 ( (\\.\\d)?$)。

That being said, ideally you should parse the string value to a doubleor floatand make what ever validations you need to make using the actual numerical value.

话虽如此,理想情况下,您应该将字符串值解析为doubleorfloat并使用实际数值进行所需的任何验证。

To parse your stringinto a doublevalue, you will need to use the Double.parseDouble(String s)like so: double myValue = Double.parseDouble(EditText.getText());

要将您解析string为一个double值,您需要像这样使用Double.parseDouble(String s)double myValue = Double.parseDouble(EditText.getText());

回答by sush

I tried your pattern using my code as following. It works perfectly as 2.1, 32.5, 444.8, 564.9 etc.

我使用我的代码尝试了你的模式,如下所示。它可以完美地作为 2.1、32.5、444.8、564.9 等。

My code:

我的代码:

public class WebPush extends Activity {  
    EditText editTxt;
    private TextView regresult;  

    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main); 

        editTxt = (EditText) findViewById(R.id.editID);
        regresult = (TextView) findViewById(R.id.txtID);

        String urName = editTxt.getText().toString();
        editTxt.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {
            }       

            @Override
            public void afterTextChanged(Editable s) {
                if (editTxt.getText().toString().matches("(^([0-9]{0,3})?)(\.[0-9]{0,1})?$"))
                {
                    regresult.setText("");
                }
                else
                {
                    regresult.setText("invalid number");
                }
            }
        });
    }
}