2

I need a regular expression that matches all numbers that are surrounded by <@! or <@ and >. The matches must not follow an odd number of backslashes but can follow a zero or even number of backslashes.

Currently, I have this regex:

(?<!\\)(?:\\{2})*(<@!|<@)[0-9]+>

The problem is that the matches include the backslashes and I need a regular expression that does not include the backslashes.

Can anyone make a regular expression that can accomplish this?

Examples:

Valid Input String: \\<@!123>
Matches: <@!123>

Invalid Input String: \\\<@!123>
Matches: none

Valid Input String: <@123>test<@456>
Matches: <@123>, <@456>

Invalid Input String: \<@123>test\\\<@456>
Matches: none

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563

1 Answers1

2

You can capture the substrings you need using the (?<!\\)(?:\\\\)*(<@!?\d+>) regex. See the regex demo.

The (<@!|<@) part in your pattern is matching either <@! or <@ and the difference is only in the ! char. So, it is logical to replace it with a simple <@!? pattern that matches <@ and then an optional ! char. Then, capture the whole (<@!?\d+> part, and get it with the Java code.

See the Java demo:

import java.util.*;
import java.util.stream.*;
import java.util.regex.*;
 
class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        String s = "1) \\\\<@!1123> 2) \\\\\\<@!2123> 3) <@3123>test<@3456> 4) \\<@4123>test\\\\\\<@4456>";
        Pattern pattern = Pattern.compile("(?<!\\\\)(?:\\\\\\\\)*(<@!?\\d+>)");
        for (String t: pattern.matcher(s).results().flatMap(g -> Stream.of(g.group(1))).toArray(String[]::new)) {
            System.out.println(t); 
        } 
    }
}

Output:

<@!1123>
<@3123>
<@3456>
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563