histelheim
histelheim

Reputation: 5098

Multiple overlapping regex matches instead of one

Consider this string:

data <- "1-FA-1-I2-1-I2-1-I2-1-EX-1-I2-1-I3-1-FA-1-I1-1-I2-1-TR-1-I1-1-I2-1-FA-1-I3-1-I1-1-FA-1-FA-1-NR-1-I3-1-I2-1-TR-1-I1-1-I2-1-I1-1-I2-1-FA-1-I2-1-I1-1-I3-1-FA-1-QU-1-I1-1-I2-1-I2-1-I2-1-NR-1-I2-1-I2-1-NR-1-I1-1-I2-1-I1-1-NR-1-I3-1-QU-1-I2-1-I3-1-QU-1-NR-1-I2-1-I1-1-NR-1-QU-1-QU-1-I2-1-I1-1-EX"

and this regex:

"(I3).{1,}(I3)"

This would match the section between the first I3 and the last I3. However, how should I modify the regex to match each separate section beginning and ending with I3? E.g.

I3-1-FA-1-I1-1-I2-1-TR-1-I1-1-I2-1-FA-1-I3
I3-1-I1-1-FA-1-FA-1-NR-1-I3
I3-1-I2-1-TR-1-I1-1-I2-1-I1-1-I2-1-FA-1-I2-1-I1-1-I3
I3-1-FA-1-QU-1-I1-1-I2-1-I2-1-I2-1-NR-1-I2-1-I2-1-NR-1-I1-1-I2-1-I1-1-NR-1-I3
I3-1-QU-1-I2-1-I3

Upvotes: 1

Views: 98

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627537

You can use a strsplit with gsub like this:

data <- "1-FA-1-I2-1-I2-1-I2-1-EX-1-I2-1-I3-1-FA-1-I1-1-I2-1-TR-1-I1-1-I2-1-FA-1-I3-1-I1-1-FA-1-FA-1-NR-1-I3-1-I2-1-TR-1-I1-1-I2-1-I1-1-I2-1-FA-1-I2-1-I1-1-I3-1-FA-1-QU-1-I1-1-I2-1-I2-1-I2-1-NR-1-I2-1-I2-1-NR-1-I1-1-I2-1-I1-1-NR-1-I3-1-QU-1-I2-1-I3-1-QU-1-NR-1-I2-1-I1-1-NR-1-QU-1-QU-1-I2-1-I1-1-EX"
data <- gsub(".*?(I3.*?)(?=I3)","\\1I3§",data,perl=T)
strsplit(gsub("[^§]*$", "", data),"§")

The .*?(I3.*?)(?=I3) regex (with \\1I3§ replacement) will remove all text before I3...I3, add a fake symbol § (you may use any you do not use), add a backup I3 for us to have complete I3 enclosed entries in the output, and then a second gsub will remove the trailing unnecessary part from the string. strsplit will do the final part - fetch you your expected results.

See IDEONE demo

Output:

[1] "I3-1-FA-1-I1-1-I2-1-TR-1-I1-1-I2-1-FA-1-I3"                                   
[2] "I3-1-I1-1-FA-1-FA-1-NR-1-I3"                                                  
[3] "I3-1-I2-1-TR-1-I1-1-I2-1-I1-1-I2-1-FA-1-I2-1-I1-1-I3"                         
[4] "I3-1-FA-1-QU-1-I1-1-I2-1-I2-1-I2-1-NR-1-I2-1-I2-1-NR-1-I1-1-I2-1-I1-1-NR-1-I3"
[5] "I3-1-QU-1-I2-1-I3"   

Upvotes: 0

Avinash Raj
Avinash Raj

Reputation: 174874

Use non-greedy form and a positive lookahead.

"(?=(I3.+?I3))"

Fetch the string you want from group index 1. Lookaheads helps to do overlapping matches. In R you must enable perl=TRUE parameter.

DEMO

Upvotes: 3

Related Questions