How to create a regex that will match anything that has 2 dimensions but will not match anything over that?

Viewed 118

I'm using a Java program and I'm trying to create a regular expression that will match anything that has two dimensions and will not match anything that goes over that.

I'm also trying to indicate two capture groups so that I can capture each dimension value separately. The dimensions have to be entered in the following format Some number x Other number (separated by the x)

Here are some examples to better explain what I'm trying to do:

  • S (26 in x 30 in): This should match and capture 26 and 30.
  • 20 x 40: This should match and capture 20 and 40.
  • Standard Size (10 x 40): This should match and capture 10 and 40.
  • 20 x 40 x 80: This should not match at all.
  • M (26 in x 30 in x 50 in): This should not match at all.

I have tried this regex but its still considering 3 dimensions as valid:

([\d.,]+).*?[xX] ?([\d,.]+).*
3 Answers

I think this should get you what you want:

^[^\d]*(\d+)[^\dx]*[xX][^\dx]*(\d+)[^\d]*$

There may be an edge case that comes up where you have an x that is not the delimiter between the two numbers though. Not sure if this is a problem for your use case.

You can see it working here regex101

Try this:

^(?!.* x .* x ).*?(\d+)(?: [a-z]+)? x (\d+)

See live demo.

More than 2 dimensions are prevented from matching due to the negative lookahead anchored to start ^(?!.* x .* x )

Note that I have addressed a variant of the original question requested by the OP in a comment below.

I have also assumed that matches are to made in the following example strings:

Extra x here is OK 31.6 x more chars a-w, y-z here is OK 81.7 same here
                   ^^^^                                  ^^^^
Numbers 78 and 81.1 before 22.5 x 31 is OK
                           ^^^^   ^^

You could use the expression

^(?!.*(?:\d+(?:\.\d+)?[^\dx]*x[^\dx]*){2}\d).*(?<![\d.])(\d+(?:\.\d+)?)[^\dx]*x[^\dx]*(?<![\d.])(\d+(?:\.\d+)?)

Demo

The following operations are performed by the regex engine.

^                 # match beginning of the string
(?!               # begin negative lookahead
  .*              # match 0+ chars
  (?:             # begin non-capture group
    \d+(?:\.\d+)? # match 1+ digits optionally followed by a period and 1+ digits
    [^\dx]*       # match 0+ chars other than digits and 'x'
    x             # match 'x'
    [^\dx]*       # match 0+ chars other than digits and 'x'
  ){2}            # end non-capture group and execute twice
  \d              # match a digit
)                 # end negative lookahead
.*                # match 0+ digits
(?<!              # begin negative lookbehind
  [\d.]           # match a digit or period
)                 # end negative lookbehind
(                 # begin capture group 1
  \d+(?:\.\d+)?   # match 1+ digits optionally followed by a period and 1+ digits
)                 # end capture group 1
[^\dx]*           # match 0+ chars other than digits and 'x'
x                 # match 'x'
[^\dx]*           # match 0+ chars other than digits and 'x'
(?<!              # begin negative lookbehind
  [\d.]           # match a digit or period
)                 # end negative lookbehind
(                 # begin capture group 2
  \d+(?:\.\d+)?   # match 1+ digits opinion followed by a period and 1+ digits
)                 # end capture group 2

Notice that expression begins with a negative lookahead that asserts there is no substring of the form

ddd ... x ... ddd ... x ... ddd

By first satisfying this requirement it becomes easier to subsequently capture the two substrings of interest.

Related