James Raitsev
James Raitsev

Reputation: 96491

How to count a position of element, relative to another element using regex?

Given String

//          1       2       3
String a = "letters.1223434.more_letters";

I'd like to recognize that numbers come in a 2nd position after the first dot

I then would like to use this knowledge to replace "2nd position of"

//          1         2           3
String b = "someWords.otherwords.morewords";

with "hello" to effectively make

//          1         2     3
String b = "someWords.hello.morewords";

Substitution would have to be done based on the original position of matched element in String a

How can this be done using regex please?

Upvotes: 4

Views: 355

Answers (3)

Pshemo
Pshemo

Reputation: 124275

For finding those numbers you can use group mechanism (round brackets in regular expresions):

import java.util.regex.*;

...

String data = "letters.1223434.more_letters";
String pattern="(.+?)\\.(.+?)\\.(.+)";
Matcher m = Pattern.compile(pattern).matcher(data);
if (m.find()) //or while if needed
    for (int i = 1; i <= m.groupCount(); i++) 
    //group 0 == whole String, so I ignore it and start from i=1
        System.out.println(i+") [" + m.group(i) + "] start="+m.start(i));
// OUT:
//1) [letters] start=0
//2) [1223434] start=8
//3) [more_letters] start=16

BUT if your goal is just replacing text between two dots try maybe replaceFirst(String regex, String replacement) method on String object:

//find ALL characters between 2 dots once and replace them 
String a = "letters.1223434abc.more_letters";
a=a.replaceFirst("\\.(.+)\\.", ".hello.");
System.out.println(a);// OUT => letters.hello.more_letters

regex tells to search all characters between two dots (including these dots), so replacement should be ".hello." (with dots).

If your String will have more dots it will replace ALL characters between first and last dot. If you want regex to search for minimum number of characters necessary to satisfy the pattern you need to use Reluctant Quantifier ->? like:

String b = "letters.1223434abc.more_letters.another.dots";
b=b.replaceFirst("\\.(.+?)\\.", ".hello.");//there is "+?" instead of "+"
System.out.println(b);// OUT => letters.hello.more_letters.another.dots

Upvotes: 1

Jonathan Henson
Jonathan Henson

Reputation: 8206

the regex for string a would be

\w+\.(\d+)\.\w+ 

using the match group to grab the number.

the regex for the second would be

\w+\.(\w+)\.\w+

to grab the match group for the second string.

Then use code like this to do what you please with the matches.

Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(inputStr);
boolean matchFound = matcher.find();

where patternStr is the pattern I mentioned above and inputStr is the input string.

You can use variations of this to try each combination you want. So you can move the match group to the first position, try that. If it returns a match, then do the replacement in the second string at the first position. If not, go to position 2 and so on...

Upvotes: 0

Christopher Oezbek
Christopher Oezbek

Reputation: 26473

What you want to do is not directly possible in RegExp, because you cannot get access to the number of the capture group and use this in the replacement operation.

Two alternatives:

  • If you can use any programming language: Split a using regexp into groups. Check each group if it matches your numeric identifier condition. Split the b string into groups. Replace the corresponding match.

  • If you only want to use a number of regexp, then you can concatenate a and b using a unique separator (let's say |). Then match .*?\.\d+?\..*?|.*?\.(.*?)\..*? and replace $1. You need to apply this regexp in the three variations first position, second position, third position.

Upvotes: 1

Related Questions