user3366706
user3366706

Reputation: 1599

Regular expression to get a match or replace a subString

I need to match or replace a part of string like below, but I couldn't write the exact regular expression for that in java.

String:

text1${text2${text3}text4}text5

Expected regex should match the test3 alone, ie. anything inside "inner" ${}. Above example has an outer ${...} and an inner ${...}, like ...${...${...}...}.... And test3 is inside the "inner ${} which is what I want.

The following regex captures the entire content within ${...}, not just the content of "inner" ${...}

\$\{(.*?)\}

More Examples:

text1${text2${text3}text4}text5 - match "text3"
text1text2${text3}text4text5    - should not match anything
text1${text2${text3}text4text5  - should not match anything

Update:

text1${text2${text3}${text4}text5} - match "text3" and "text4"

Upvotes: 1

Views: 377

Answers (2)

Shakiba Moshiri
Shakiba Moshiri

Reputation: 23774

First you need to match the entire between the first { and the last } and after that you can match what you want by using match-group.

what you want
{.*\{(.*?)\}.*?\}

In the first step it match {text2${text3} and after that you should use math-group

I am not familiar with Java but I know a little with Perl and C++ and I think it works in Java because it is easy and not complex

demo


Test with Perl

echo 'text1${text2${text3}text4}text5' | perl -lne '/\{.*\{(.*?)\}.*?\}/ && print $1'

output

text3


So in you Java code use $1 that's it.


For your update that you wrote, you have 2 choices one with a loop over your string and other with four match-group

First with a while loop
echo 'text1${text2${text3}${text4}text5}' | perl -lne 'print $2 while /(\${)(\w+)(\$?})/g'
text3
text4
How does it work? very easy. It first match ${text3} and here \w+ would be text3 then it goes ahead and match ${text4} and again \w+ would be text4
(\${)(\w+)(\$?})
prove

Second with non-loop
echo 'your-string' | perl -lne ' /(\${)(\w+)(\$?})\1(\w+)\3/g && print $2," ",$4'

This one also easy. It first matches text3 and then matches text4 and puts them in $2 and $4. that's it.
(\${)(\w+)(\$?})\1(\w+)\3
prove

NOTE
With while loop you need to use g flag and you can not ignore it but for second no problem.
Again

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626748

The . matches both { and }. You need to exclude matching { and }:

\$\{([^{}]*)}
     ^^^^^

See the regex demo. The [^{}]* is a negated character class matching 0+ chars other than { and }.

Java code:

String str = "text1${text2${text3}text4}text5";
Pattern p = Pattern.compile("\\$\\{([^{}]*)}");
Matcher m = p.matcher(str);
while (m.find()) {
    System.out.println(m.group(1));
}
// => text3

Upvotes: 2

Related Questions