Regular expression, match between the first, second, third etc. occurences of a pair of words

Viewed 97

I would like to find a regular expression that matches the bold text in the string below.

"A1 text: XXX \r\n Status: No \r\n Info: YYYY \r\n UUUU End A2 text: BBB \r\n Status: Yes \r\n Info: VVV \r\n OOO End A3 2020/2021"

My problem is the match between the pair "Info" and "End. My regex below matches everything between the first occurence of "Info" and the last of "End". I want it to match the first "Info" and the next "End". Thereafter the next "Info" and the "End" that comes after.

string <- "A1 text: XXX \r\n Status: No \r\n Info: YYYY \r\n UUUU End A2 text: BBB \r\n Status: Yes \r\n Info: VVV \r\n OOO End A3 2020/2021"

str_match_all(string, regex("text: *([^\\r\\n]+?)\\r\\n.*?Status: *([^\\r\\n]+?)\\r\\n.",
                           dotall=T))[[1]][,-1]

str_match_all(string, regex("(?<=Info)(.*)(?=End)",
                            dotall=T))[[1]][,-1]


I want a expression like this: 
str_match_all(string, regex("text: *([^\\r\\n]+?)\\r\\n.*?Status: *([^\\r\\n]+?)\\r\\n.*?(?<=Info)(.*)(?=End)",   dotall=T))[[1]][,-1]

to return this:

     [,1]   [,2]  [,3]
[1,] "XXX " "No " "YYYY \r\n UUUU"
[2,] "BBB " "Yes " "VVV \r\n OOO"


1 Answers

You can use

string <- "A1 text: XXX \r\n Status: No \r\n Info: YYYY \r\n UUUU End A2 text: BBB \r\n Status: Yes \r\n Info: VVV \r\n OOO End A3 2020/2021"
library(stringr)
res <- str_match_all(string, "(?s)text:\\h*(.*?)\\R\\s*Status:\\h*(.*?)\\R\\s*Info:\\h*(.*?)\\s*End\\b")
lapply(res, function(m) m[,-1])
# => [[1]]
# =>      [,1]   [,2]   [,3]            
# => [1,] "XXX " "No "  "YYYY \r\n UUUU"
# => [2,] "BBB " "Yes " "VVV \r\n OOO"  

The regex is

(?s)text:\h*(.*?)\R\s*Status:\h*([^\r\n]*)\R\s*Info:\h*(.*?)\s*End\b

See the online regex demo. Details:

  • (?s) - the inline dotall modifier
  • text: - literal text
  • \h* - 0+ horizontal whitespaces
  • (.*?) - Group 1: any zero or more chars, as few as possible
  • \R - any line break sequence
  • \s* - any 0+ whitespaces
  • Status:\h* - Status: and 0+ horizontal whitespaces
  • ([^\r\n]*) - Group 2: any zero or more chars other than CR and LF
  • \R - any line break sequence
  • \s* - any 0+ whitespaces
  • Info:\h* - Info: and 0+ horizontal whitespaces
  • (.*?) - Group 3: any zero or more chars, as few as possible
  • \s*End\b - 0+ whitespaces, End as a whole word.
Related