Hot questions for Using Android EditText in regex

Question:

I am working on Java code syntax highlighting in Android (Editext).

Using regex to highlight keywords, literals, strings, number.

Regex am using to highlight string String regex : "\"(.*?)\"|'(.*?)'"

Comment regex : "/\\*(?:.|[\\n\\r])*?\\*/|//.*+\\/\\/.*"

Sequence of regex selection is keywords regex...........string regex and last comment regex.

Above regex is doing the proper selection of normal string and comments but..

Problem is

Comments inside double quotes also get highlighted. I want to ignore comment selection inside double quotes.

Please go through the image for better understanding of problem(expected output) Anyone help or guidance will be appreciated


Answer:

To me, it seems like you are simply searching for all matches of each regex. If a regex matches, you color the match. Thus, you overwrite the color of a previous match with the color of the last match.

To solve this issue, you have to use a proper lexer that is able to translate a given input text into a stream of tokens. Then, you can run over the token stream and when you encounter a token that needs to be colored, you can do this.

This prevents the current issue, that one part of the input text is matched by multiple regex and thus colored multiple times. It prevents it, because each character of the input text is associated to exactly one token in the token stream.


A lexer that uses the first longest match algorithm works like this: It searches for all regex matches that start at the beginning of the input text. It chooses the regex that has the longest match. If there are multiple regex that share the longest match, it chooses the first one. Now the lexer creates the first token of the token stream. The token consists of the token type (which is given by the regex), the start position of the match and the end position of the match. Next, the lexer searches for the next token by doing the above again. However this time, it searches for matches that start at the end position of the previous token. The lexer does this until the complete input text is transformed into a token stream, or until it encounters an invalid input.

The important part here is, that the end position of token n and the start position of token n + 1 is the same. Thus, there is no overlap and thus there is always only one color.

Question:

I'm trying to write a regular expression for an Android project. The widget this is concerning is the MaterialEditText found here https://github.com/rengwuxian/MaterialEditText

This edit text has a method to chain together RegExp validators to it. So far I managed to come up with this.

"^[a-zA-Z\\s]*$"

When it doesn't match this pattern it shows an error. I need to chain another addValidator to it to check if the edit text is blank, how do i do that?

Update

I tried this code

editText.addValidator(
            new RegexpValidator("Must contain letters only", "^[A-z][\\sA-z]*$")).addValidator(new RegexpValidator("Cannot be blank","^$"));

When its blank, im getting the "Must contain letters only error", and when i type any data i get the "Cannot be blank"


Answer:

  1. Your regex does allow the leading whitespace, which your question sounds like it should not.
  2. To disallow blank input you could just use + instead of *, but combined with the fix for #1 this won't be necessary.

Something like this should work: ^[A-z][\sA-z]*$

Question:

I am trying to pass a text output into a regex method whereby I can take this entire text output and extract out the email address.

For example, I have the text output below:

Taria Joseph
General Manager

96523325
tariajoseph@hotmail.com

I want to pass the above text output into the regex method and extract out "tariajoseph@hotmail.com" and display into an EditText.

Below are my codes:

public class CreateContactActivityOCRtest extends Activity {

private String recognizedText, textToUse;
private EditText mEditText1, mEditText2;
private String mFromLang, mCurrentLang;

private Pattern pattern;
private Matcher matcher;

private static final String EMAIL_PATTERN =
        "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
                + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_createcontact);

    // Getting the path of the image to show
    Bundle extras = this.getIntent().getExtras();
    recognizedText = extras.getString("TEXT");
    textToUse = recognizedText;

    // Getting the language used for text recognition
    mFromLang = extras.getString("LANG");
    mCurrentLang = mFromLang;
    //Log.i(TAG, mFromLang);

    textToUse = EmailValidator();
    setupUI();
}

public String EmailValidator() {

    String email = textToUse;

    Pattern pattern = Pattern.compile(EMAIL_PATTERN);
    Matcher matcher = pattern.matcher(email);

    if (matcher.find()) {
        return email.substring(matcher.start(), matcher.end());

    } else {
        // TODO handle condition when input doesn't have an email address
    }

    return email;

}

public boolean validate(final String hex) {

    matcher = pattern.matcher(hex);
    return matcher.matches();

}

public void setupUI(){

    // Setting up the textbox

    mEditText1 = (EditText)findViewById(R.id.EmailET);
    mEditText2 = (EditText)findViewById(R.id.role);
    mEditText1.setText(textToUse);
    mEditText2.setText(textToUse);

}

}

What I am trying to do is:

  1. Receive the text output from another class (Already done)
  2. Pass Entire Text Output into EmailValidator() (Not sure if I did it correctly)
  3. Take the output from EmailValidator() and pass it to setupUI() (Not done)

Can someone help me check on which part did it go wrong? Is it the passing of methods, or error in my regex method (EmailValidator())?

Currently when testing on the device, the page straight away display the entire text output to the EditText.


Answer:

you can check email validation Here. change your code like as below

protected void onCreate(Bundle savedInstanceState) {    
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_createcontact);   
mEditText1 = (EditText)findViewById(R.id.EmailET);
mEditText2 = (EditText)findViewById(R.id.role);
Bundle extras = this.getIntent().getExtras();
if (extras != null) {
recognizedText = extras.getString("TEXT");
mFromLang = extras.getString("LANG");
textToUse = recognizedText;  
mCurrentLang = mFromLang;   
// textToUse = EmailValidator(textToUse);

if(isValidEmail(recognizedText))
{
textToUse=recognizedText   
 }
else
{
//this is invalid email part
}

setupUI();      
}


public final static boolean isValidEmail(CharSequence target) {
if (TextUtils.isEmpty(target)) {
return false;
} else {
return android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();
}
}


 public void setupUI(){    
 mEditText1.setText(textToUse);
 mEditText2.setText(textToUse);
 }

Question:

I implement an EditText that allows to input prices separated by a space. The prices can be both integer and decimal values.

For example:

3900 156.2 140.38 200 10

So, I've found the following regex:

(\d+([.]\d{1,2})? )+

But it works only with a space at the end. (I know it's absolutely expectable)

Is it possible to make this regex to ignore a space at the end of input string?

Or maybe you can suggest smth else?

Thanks.


Answer:

I would suggest the following pattern:

^\d+(?:\.\d+)?(?:\s+\d+(?:\.\d+)?)*$

In plain English, this says to match a (possibly) decimal number, followed by one or more whitespace characters, and another (possibly) decimal number, that happening zero or more times.

Have a look at the demo link below.

Demo

But since you're using Java, I can suggest an alternative here. Since you will likely have to access each number, you could instead split the string coming from the EditText by space, and then check each "number" to make sure it really is a number. Something like this:

String input = "3900 156.2 140.38 200 10";
String[] nums = input.split("\\s+");
for (String num : nums) {
    if (num.matches("\\d+(?:\\.\\d+)?")) {
        // then process this as a number
    }
}

Question:

[FIRST APP] I am providing users with an option to have multiple profiles using different preference files. The users can name their profiles themselves. I have made a custom dialog box to take filename as input in edittext. A valid filename should contains only [A-Z, a-z, 0-9, _, -]. I am letting the user know about this restriction.

Whenever a user enters an invalid character, I want that character to be deleted from edittext and preferably display a toast. After a brief search I believe that this task can be performed easily using regular expressions (as compared to my naive string based approach using textwatcher on edittext). But, I have never worked with regex before and need help regarding this.

ps - A concerning usecase is when the user goes berserk and types random character in edittext.


Answer:

Here is the working code for above specific scenario, we attach a textwatcher to our edittext and then verify the input using a pattern (Thnaks to huidube) :

    profile_name.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

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

        @Override
        public void afterTextChanged(Editable s) {
            String str = s.toString();
            if (!(str.matches("[a-zA-Z0-9-_ ]*"))) {
                str = removeIllegalChar(str).trim(); //trim whitespaces
                profile_name.setText(str);
                profile_name.setSelection(str.length());  //use only if u want to set cursor to end
            }
        }
    });

    private String removeIllegalChar(String str) {
    for (int i=0; i < str.length(); i++) {
        if (!(String.valueOf(str.charAt(i)).matches("[a-zA-Z0-9-_ ]*"))) {
            //as the callback is called for each character entered, we can return on first non-match
            //maybe show a short toast        
            return str.substring(0, i) + str.substring(i+1);
        }
    }
    return str;
}

I have two test devices, one a dying veteran and a Moto G and the above procedure works smoothly on both. So, I guess this is acceptably optimal.