开发者

Negative look ahead java

I need an expression to capture a string like this:

"A"[A string that is NOT atleast 5 and atmost 6 digits]"B", In other words capture anything that is NOT the following

A[0-9][0-9][0-9][0-9][0-9]B

A[0-9][0-9][0-9][0-9][0-9][0-9]B

I have tr开发者_运维技巧ied the negative look ahead

regex = "a((?![0-9]{5,6}).)*d" ;

But it fails to capture all scenarios.


A(?!\d{5,6}B).*B

You only want to do the lookahead once, right after the A. And you have to include the B in the lookahead so it doesn't reject anything with more than six digits.


This is just a few lines of really simple, understandable, reliable code that you could have written and rewritten 3 times in the amount of time it takes you to post and get a response to the RE version. (And, of course, with the RE version it won't be obvious what you are doing).

int examine(String s) {
    int foundAt=-1;

    for(int i=0;i<s.length;i++) {
        char c=s.charAt(i); // something like that
        if(c=='A') { 
            foundAt=i;               
            continue;
        }

        if(foundAt != -1) {
            if(c == 'B' && i-foundAt < 5 || i-foundAt > 6)
                return foundAt;  

            if(!String.isNumber(c)) // something like that
                foundAt = -1;  // Not a number before B, reset
        }
    }
    return -1;
}

Okay, so it's slightly more than a few lines (but it is wrapped in a function call too), but modifying the behavior to do something tricky is more straight forward than modifying an RE where changes can easily incur unintended consequences, it should be trivial to read, and once the first few simple bugs are wiped out, it will be foolproof--something that seems to never be true of regular expressions.

So, isn't this about as short and readable as you are going to get?

n=examine(s);

Any "advantage" of shorter code is completely eliminated if replaced by an easy to read, reliable function call.

(I figure there is a good chance this is a homework question and this should NOT properly answer it if it is)


You almost have it. Try this instead:

"A(?![0-9]{5,6}B).*B"

Note that ".*" will match greedily; if there are multiple occurrences of B, the match will end with the last, not the first. You may want to use ".*?" instead. For example, if you have a long string with multiple occurrences of this pattern, and you are using the find() method to scan over the input string, you'd want to match reluctantly.


Is this a homework question?

I'm not sure why you have an "a" and "d" in your regex.

This will handle anything from 0 to 4 digits and 7 or more digits.

String rexexp = "A(\\d{0,4}|\\d{7,})B";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜