4

The regex is -?([0-9]|([1-9][0-9])).

The number is -2231 and it's being matched. From my understanding, it should be a single digit or double digits.  Why is this number matched with this regex?

Rashad
  • 141
  • 2
  • 5
    A match can be found in the string, but it doesn't match the whole string. – martin Feb 09 '18 at 01:20
  • @Jeff Schaller:  The original version of this question contained a regular expression in (ordinary, single) quotes, and you *added* back ticks without removing the quotes.  That makes it look like the single quotes are part of the regex that the OP is asking about, which makes the question very confusing. – G-Man Says 'Reinstate Monica' Feb 16 '18 at 04:57
  • Sorry for the confusion, @G-man. I’m accustomed to seeing regexes in quotes to protect them from shell interpretation. The number wouldn’t have matched a regex that required quote marks, but it’s better to be clear about things, so thank you for the improvement! – Jeff Schaller Feb 16 '18 at 11:00
  • @Jeff Schaller:  Yeah, it occurred to me later that, if I had seen the regex in quotes in the context of a command line, it would have been perfectly clear. – G-Man Says 'Reinstate Monica' Feb 16 '18 at 15:13

2 Answers2

21

The regular expression is not anchored, so it's free to match the first 1 or two numbers and "succeed", leaving the trailing numbers (successfully) unmatched.

If you require 1 or 2 digit numbers, anchor the regex:

'^-?([0-9]|([1-9][0-9]))$'

Some examples:

$ seq -100 -99 | grep -E '^-?([0-9]|[1-9][0-9])$'
-99

$ seq 99 100 | grep -E '^-?([0-9]|[1-9][0-9])$'
99

$ seq -9 9  | grep -E '^-?([0-9]|[1-9][0-9])$'
-9
-8
-7
-6
-5
-4
-3
-2
-1
0
1
2
3
4
5
6
7
8
9

$ seq -2231 -100 | grep -E '^-?([0-9]|[1-9][0-9])$'
(empty)
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
14

Most programs that use regex patterns actually implement a search of the pattern, instead of a full-string match. Python has distinct search() and match() methods where search() matches anywhere in the string, and match() only at the beginning. grep has the -x option to demand a match against the whole string; by default it matches anywhere in the string. Others, like sed, awk and Perl will happily look for the pattern anywhere in the string. Use the ^ and $ modifiers ("anchors") to force the pattern to the start or end of the string (respectively).

So, the ERE pattern you want is probably this:

^-?[1-9]?[0-9]$
ilkkachu
  • 138,973
  • See also expr that anchors at the start but not at the end (uses BREs though, not those EREs). – Stéphane Chazelas Feb 08 '18 at 16:17
  • 5
    I like this answer because it explains that regular expressions can only be evaluated in the context in which they're used. Sometimes the regex must match the entire string, other times it must only be found somewhere within another string. The OP's question can't be answered without understand what program or function the regex is used within. – Syntax Junkie Feb 08 '18 at 22:12
  • i just put the number in vi editor – Rashad Feb 11 '18 at 00:54