0

I have a list of strings and multiple combinations of conditions to run against them which I want to combine with AND and OR.

Example Rules:

  • starts with 12
  • exact match 14444 (old value from comments ->12333)
  • does not start with 127

The final check would be similar to: ((exact match 14444) OR (starts with 12)) AND (does not start with 127)(prevent 14444 to be part of a larger string).

Inspired from this post https://stackoverflow.com/a/870506/15272947 ,I got as far as this:

^((?=.*^12)|(?=.*^14444))(?=^(?:(?!^127).)*$).*

It works for start with conditions, but it does not work for exact match. In this case it should match 14444, but not 144445.

  • 1
    The rules are very weird. The first implies the second, and the third implies the first and second... – Sweeper Feb 24 '21 at 07:55
  • Changed them a bit, but I am combining strange rules that might be implied in another one, that is why I want them to be "independent" of one another. The main problem is making the exact match a priority – melcuturbat Feb 24 '21 at 08:01
  • So you want it to check the "exact match" rule first. If it doesn't match, it has to satisfy all the other rules? – Sweeper Feb 24 '21 at 08:03
  • Exactly. But the rules are generated programmatically and I need a "standard template" for each type of rule. – melcuturbat Feb 24 '21 at 08:06

2 Answers2

0

Here is a generic regex that does what you ask for, with match/no match test cases:

const regex = /^(?!127)(?:14444$|12)/;
[ '1',
  '12',
  '123',
  '127',
  '128',
  '1444',
  '14444',
  '14444999'
].forEach(str => {
  console.log(str + ' => ' + regex.test(str))
});

Output:

1 => false
12 => true
123 => true
127 => false
128 => true
1444 => false
14444 => true
14444999 => false

Explanation:

  • ^ - start of string
  • (?!127) - negative lookahead for 127 (what follows is ANDed)
  • (?:14444$|12) - non-capturing group expecting exactly 14444 OR string starting with 12
Peter Thoeny
  • 7,379
  • 1
  • 10
  • 20
  • Thanks! The thing I can't figure out is how to make 12333999 not match in this case because it matches exactly 12333. So the result I am looking for is 1->false, 12->true, 123->true, 127->false, 128->true, 1233->true, 12333999 -> false (because it has an exact match of 12333 and something else after 12333). – melcuturbat Feb 24 '21 at 08:35
  • And the biggest problem is that I have to do this programmatically with a lot of rules, so they must have some kind of "standard template" for each type of rule. – melcuturbat Feb 24 '21 at 08:36
  • `starts with 12` and `exact match 12333` are redundant. So `^12(?!7)` is pretty much enough – Hao Wu Feb 24 '21 at 08:36
  • Your requirement of "exactly 12333" OR "starts with 12" is redundant. Based on this rule, `12`, `1233`, `12333`, `12334`, `1233399` are all true. Please be more crisp with your requirement. – Peter Thoeny Feb 24 '21 at 08:54
  • @PeterThoeny, My interpretation of a better description of the "exact" match rule would be: *"Prevent 12333 to be part of a larger string, thus prevent following digits"*. I guess indeed OP needs to clarify that better. – JvdV Feb 24 '21 at 09:10
  • @JvdV yes you are right, it should prevent 12333 to be part of a larger string – melcuturbat Feb 24 '21 at 09:15
  • What about `12`, `1233`, `12334`, `12334999`? All true? – Peter Thoeny Feb 24 '21 at 09:23
  • you guys were right, the example was not good, edited it – melcuturbat Feb 24 '21 at 09:30
  • I updated the answer accordingly. Does this fit your needs? – Peter Thoeny Feb 24 '21 at 09:59
0

I think I was missing a "$" after 1444. Although I don't think this looks that pretty, there might be a better method of doing it and I might have extra things that are not needed as this is the first regex I write :).

^((?=.*^12)|(?=.*^1444$))(?=^(?:(?!^127).)*$).*

The most important thing was to have independent components of the rule for each type of condition (e.g. start with, does not start with, exact match...) so you can generate them programmatically and combine an undefined number of conditions.

Thanks for the comments and help.