0

I need a way for matching a "format" string. It should have either one or two %d tokens, any only one %s token. Also preferably it wouldn't allow any other formatting tokens such as %f etc. I've come up with a few halfway-solutions of my own that do not manage to get the full job done:

.*?(\%d).*(\%(?=d|s)).*   //Doesn't fit requirements
.*?(\%d).*(\%d).*(\%s).*  //Doesn't allow for any ordering of the tokens

My thought is perhaps searching for the sole %s token and doing lookarounds, but I'm not entirely certain how to go about doing that (regex is not my strongest suit). This is intented for use an a Java library, and I'm open to non-regex solutions, however regex solutions need to match the entire string (and I'd prefer not doing two/three different regex searches on a format string).

It should match %d:%d:%s as well as %d:%s for example, but not %d:%d:%d:%s or %f:%d:%s. Essentially this would be the requirements of the string:

  • One or two %d tokens
  • One %s token
Rogue
  • 11,105
  • 5
  • 45
  • 71
  • could you provide an example? – Avinash Raj Dec 27 '14 at 13:53
  • possible duplicate of [Regex: I want this AND that AND that... in any order](http://stackoverflow.com/questions/3533408/regex-i-want-this-and-that-and-that-in-any-order) – Barmar Dec 27 '14 at 13:55
  • I updated my question a little @AvinashRaj – Rogue Dec 27 '14 at 13:55
  • @Barmar the problem I'm seeing with those is I would want to match one *or* two of the `%d` tokens. – Rogue Dec 27 '14 at 13:56
  • You can combine it with negative lookaround so it only matches the specified number. – Barmar Dec 27 '14 at 13:57
  • Unfortunately my regex skills are subpar at best :( . If I was able to whip that up I wouldn't be here hours into working on this. – Rogue Dec 27 '14 at 13:58
  • @AvinashRaj Yup! That's the concept, it's going to be passed to `String#format`, so I just want everything to pass except extra formatting tokens. – Rogue Dec 27 '14 at 14:39

1 Answers1

3

You could use the below regex which uses lookarounds.

^(?!.*%[^sd])(?!.*%d.*%d.*%d)(?!.*%s.*%s)(?=.*%s)(?=.*%d).*$

DEMO

Explanation:

  • (?!.*%[^sd]) String won't contain formatting characters other than %d or %s

  • (?!.*%d.*%d.*%d) String won't contain atleast three %d characters.

  • (?!.*%s.*%s) String won't contain atleast two %s characters.

  • (?=.*%s) String must contain a %s character.

  • (?=.*%d) String must contain a %d character.

  • Match the corresponding string only if all the above conditions are satisfied.

Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
  • I added a `(?=.*%d)` as well to at least require a single `%d`, but this worked, thanks! – Rogue Dec 27 '14 at 14:46