2

I understand the basics of regex but I am not able to create a regular expression satisfying all these conditions. Can anybody give me an idea how to do it.

  1. The string must be at least 20 character long
  2. The string must contain a digit
  3. The digit must be preceded by some non-numeric character
  4. The end of the string must be a date of format DD/MM/YYYY HH:MM - yes, there is a space in between and all the digits must be present. Digits occurring in the date part of the string are not considered as satisfiability condition of rule 2.
  5. If there is a $ sign before the first numeric digit occurs, the string is invalid

I have tried using code:

if (sCurrentLine.length() > 20) {   
    for (int i=0; i <= sCurrentLine.length() - 1; i++) {
        char character = sCurrentLine.charAt(i);
        int ascii = (int) character;
        if (((ascii >= 48) && (ascii <= 57)) && (i!=0)) {
            char character2 = sCurrentLine.charAt(i-1);
            int ascii2 = (int) character2;
            if(!((ascii2 >= 48) && (ascii2 <= 57))) {
                 // 
            }
        }
    }
}

but it seems too complicated.

Is there a regex approach that could solve this?

9
  • Have you managed to satisfy any of the conditions? If so, post it up. Commented Aug 26, 2014 at 14:53
  • 2
    I think we will need 3 things sample inputs, sample outputs and what you have so far... Commented Aug 26, 2014 at 14:53
  • @Bathsheba Yeah But i used a loop to go through the string to do the first 2 Commented Aug 26, 2014 at 14:53
  • can you show us your effort? Commented Aug 26, 2014 at 14:54
  • 1
    "the end of the password must be a date of format DD/MM/YYYY HH:MM" ? Wh–, wait, what? Not sure whether to laugh or to cry Commented Aug 26, 2014 at 14:56

3 Answers 3

2

Try this:

if (sCurrentLine.matches("(?=.{20})[^$]*[^\\d$]\\d.*\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}")) 

The length is checked using a look ahead that asserts there are 20 chars (which of course means there are at least 20 chars).

Your required-digit logic may be expressed as "starts with any number of non-dollar chars, a non-dollar/digit char then a digit", which is the first part of the regex.

The last part is the date format. Note that this checks only that there are digits in the right place, not that it's a legitimate date.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks that decreases my search range. Is it possible to include the month-time part in the expression ?
oops - added end with date that is not the initial digit
+ 1 - Clearer and more precise than the answer I was about to post.
Just to complete: aa1$10/12/2014 12:25 is a valid password (the date part is took in account in the 20, should be 36 if you wish 20 chars before the date)
0

This should do except one point: the length of 20 wich is easy to check around:

Demo Regex used: (\D+(?<!\$)\d.+)(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2})

Edit: it captures the string as first group and the "date" as second group. So it should be easy to check first is > 20 and that the second is a valid date.

Matching a valid date with a regex is quite a pain and there's library for that (which will take in account leap years etc.)

Comments

0

Trying to do this with a lookahead seems difficult. I tried some mechanisms where the first part of the string is 4 or more characters (note that the MM/DD/YYYY HH:MM portion will need to be exactly 16 characters), and a lookahead is used to make sure that 4+-character portion has a digit preceded by a non-digit that isn't $. Unfortunately, I don't know how to get the lookahead to stop at the end of that first portion. Perhaps using lookbehind will work.

But I'd recommend just splitting into two regexes. Anything that uses one regex is going to be a whole lot less readable and probably less efficient.

if (sCurrentLine.length >= 20 &&
    sCurrentLine.substring(sCurrentLine.length() - 16, sCurrentLine.length())
        .matches("\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}") &&
    sCurrentLine.substring(0, sCurrentLine.length() - 16)
        .matches("[^$]*[^\\d$]\\d"))

This makes sure that the last 16 characters match the date/time format, and the first part of the string has a character that isn't a digit or $, followed by a digit.

Note: not tested

Edit: I interpreted condition 5 as meaning there can't be an $ immediately preceding the first digit, but I think I got this wrong. Now makes sure there isn't an $ anywhere before the first digit.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.