Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match every thing between "****" or [****]

Tags:

regex

I have a regex that look like this:

(?="(test)"\s*:\s*(".*?"|\[.*?]))

to match the value between "..." or [...]

Input

"test":"value0"
"test":["value1", "value2"]

Output

Group1     Group2
test       value0
test       "value1", "value2" // or - value1", "value2

I there any trick to ignore "" and [] and stick with two group, group1 and group2?

I tried (?="(test)"\s*:\s*(?="(.*?)"|\[(.*?)])) but this gives me 4 groups, which is not good for me.

like image 799
YCF_L Avatar asked Jan 24 '23 11:01

YCF_L


2 Answers

You may use this conditional regex in PHP with branch reset group:

"(test)"\h*:\h*(?|"([^"]*)"|\[([^]]*)])

This will give you 2 capture groups in both the inputs with enclosing " or [...].

RegEx Demo

RegEx Details:

  • (?|..) is a branch reset group. Here Subpatterns declared within each alternative of this construct will start over from the same index
  • (?|"([^"]*)"|\[([^]]*)]) is if-then-else conditional subpatern which means if " is matched then use "([^"]*)" otherwise use \[([^]]*)] subpattern
like image 183
anubhava Avatar answered Jan 29 '23 10:01

anubhava


You can use a pattern like

"(test)"\s*:\s*\K(?|"\K([^"]*)|\[\K([^]]*))

See the regex demo.

Details:

  • " - a " char
  • (test) - Group 1: test word
  • " - a " char
  • \s*:\s* - a colon enclosed with zero or more whitespaces
  • \K - match reset operator that clears the current overall match memory buffer (group value is still kept intact)
  • (?|"\K([^"]*)|\[\K([^]]*)) - a branch reset group:
    • "\K([^"]*) - matches a ", then discards it, and then captures into Group 2 zero or more chars other than "
    • | - or
    • \[\K([^]]*) - matches a [, then discards it, and then captures into Group 2 zero or more chars other than ]

In Java, you can't use \K and ?|, use capturing groups:

String s = "\"test\":[\"value1\", \"value2\"]";
Pattern pattern = Pattern.compile("\"(test)\"\\s*:\\s*(?:\"([^\"]*)|\\[([^\\]]*))");
Matcher matcher = pattern.matcher(s);
while (matcher.find()){
    System.out.println("Key: " + matcher.group(1)); 
    if (matcher.group(2) != null) {
        System.out.println("Value: " + matcher.group(2)); 
    } else {
        System.out.println("Value: " + matcher.group(3)); 
    }
} 

See a Java demo.

like image 23
Wiktor Stribiżew Avatar answered Jan 29 '23 08:01

Wiktor Stribiżew