KMC
KMC

Reputation: 20046

Why Regex isMatch gives false when it is true?

I have a piece of C# code that validates a textbox field to be positive numeric

Regex isPositiveInt = new Regex("[^0-9]");
return !isPositiveInt.IsMatch(textbox1.Text)

I found if the regex matches, it gives "false" and when it doesn't match, it gives "true". So I have to add a "!" to the return value. There is no problem with that, but I feel it's counterintuitive. Can someone please explain why it return a opposite result?

Upvotes: 1

Views: 11853

Answers (6)

Leo
Leo

Reputation: 399

I think below will fill exactly what you looking for

this will check for integers without decimal

\A([0-9]*)\z

This will even recognize decimal

\A([0-9])\z|\A(\d.(\d)*)\Z

Upvotes: 0

Michael Low
Michael Low

Reputation: 24506

The ^ meta-character has two meanings in regexes - to mark the start of the string when used by itself, and as part of the [^...] pattern meaning "don't match any of the characters in the [...] block". I think perhaps you intended ^[0-9] instead, which will match any string that starts with a digit. It won't make sure the whole string is numeric though, as it only checks the first character and anything could come after that.

If you want to make sure your string is numeric, just ^\d+$ is the way to go. \d is identical to [0-9] but easier to read, and ^ and $ mark the start and end of the string respectively.

Upvotes: 7

Stephen Chung
Stephen Chung

Reputation: 14605

[^0-9] will match a single character that is not a digit.

Is this what you want?

Are you sure you don't mean \d+ instead?

You thought it worked in reverse because if you are only testing positive and negative numbers, the only non-digit characters you'll be using will be "-" (the negative sign). So it will match the negative sign because it is not a digit. Thus you find that your code works in reverse.

E.g. "-987" (true: matches the negative sign), "123" (false: no non-digit character found)

Therefore, the truth is: your code does not work in reverse. Your code is wrong, and does the wrong thing. It is just that your inputs are such that it looks like it is working in reverse.

Upvotes: 5

Guffa
Guffa

Reputation: 700362

Your regular expression is a negative set, so it will match one single character from the string that is not a digit.

Example of results:

""     false
"0"    false
"1"    false
"x"    true
"42x"  true

You could use this to catch illegal characters in the input, but as you see you can't use it to distinguish between an empty input and a numeric input.

To match only digits, you would match both the beginning and the end of the string (using ^ and $), and at least one digit in between:

Regex isNonNegativeInteger = new Regex(@"^\d+$");

To match a positive integer (which I'm not certain that you actually want), you would have to make sure that the value is not zero. This would match a number where one of the digits is not zero:

Regex isPositiveInteger = new Regex(@"^\d*[1-9]\d*$");

Upvotes: 2

sehe
sehe

Reputation: 393114

The real answer to

There is no problem with that, but I feel it's counterintuitive. Can someone please explain why it return a opposite result?

Is really: it doesn't. Look twice :)

On the plus side: you're intuition is still working ok. You can learn to trust it.

Sorry if that seems a bit pedantic, but it handn't been clearly stated, and I think in a way it deserves to be the accepted answer. We try to answer the question. Since others have been plenty helpful beyond that, I don't have to repeat that info :)

Upvotes: 0

Ferruccio
Ferruccio

Reputation: 100668

The ^ in the regex character class means: is NOT in the set of 0 to 9. To match positive integers you want:

[0-9]+

meaning one or more characters from the set of 0 to 9.

Note: this will also match 0 which, strictly speaking, is not a positive integer. The expression actually matches non-negative integers.

Upvotes: 1

Related Questions