You should be able to debug the regex you wrote.
> as.regex(pattern2)
<regex> ([\d]+)\.\s((?:[\w]+|[\w]+\s[\w]+))\s(\d\.[\d]+)
Plug it in at regex101, and you see your strings do not always match. The explanation on the right tells you that you only allow 1 or 2 space separated words between the dot and number. Also, WRD
([\w]+
pattern) does not match dots and any other chars that are not letters, digits or _
. Now, you know you need to match your string with
^(\d+)\.(.*?)\s*(\d\.\d{2})$
See this regex demo. Translating into Rebus:
pattern2 <- START %R% # ^ - start of string
capture(one_or_more(DGT)) %R% # (\d+) - Group 1: one or more digits
DOT %R% # \. - a dot
"(.*?)" %R% # (.*?) - Group 2: any 0+ chars as few as possible
zero_or_more(SPC) %R% # \s* - 0+ whitespaces
capture(DGT %R% DOT %R% repeated(DGT, 2)) %R% # (\d\.\d{2}) - Group 3: #.## number
END # $ - end of string
Checking:
> pattern2
<regex> ^([\d]+)\.(.*?)[\s]*(\d\.[\d]{2})$
> companies <- c("612. Grt. Am. Mgt. & Inv. 7.33","77. Wickes 4.61","265. Wang Labs 8.75","9. CrossLand Savings 6.32","228. JPS Textile Group 2.00")
> str_match(companies, pattern = pattern2)
[,1] [,2] [,3] [,4]
[1,] "612. Grt. Am. Mgt. & Inv. 7.33" "612" " Grt. Am. Mgt. & Inv." "7.33"
[2,] "77. Wickes 4.61" "77" " Wickes" "4.61"
[3,] "265. Wang Labs 8.75" "265" " Wang Labs" "8.75"
[4,] "9. CrossLand Savings 6.32" "9" " CrossLand Savings" "6.32"
[5,] "228. JPS Textile Group 2.00" "228" " JPS Textile Group" "2.00"
WARNING: the capture(lazy(zero_or_more(ANY_CHAR)))
returns ([.]*?)
pattern that matches 0 or more dots as few as possible instead of matching any 0+ chars, because rebus
has a bug: it wraps all the repeated
(one_or_more
or zero_or_more
) chars with [
and ]
, a character class. That is why (.*?)
is added "manually".
This can be resolved, or worked around, using a common construct like [\w\W]
/ [\s\S]
or [\d\D]
:
pattern2 <- START %R% # ^ - start of string
capture(one_or_more(DGT)) %R% # (\d+) - Group 1: one or more digits
DOT %R% # \. - a dot
capture( # Group 2 start:
lazy(zero_or_more(char_class(WRD, NOT_WRD))) # - [\w\W] - any 0+ chars as few as possible
) %R% # End of Group 2
zero_or_more(SPC) %R% # \s* - 0+ whitespaces
capture(DGT %R% DOT %R% repeated(DGT, 2)) %R% # (\d\.\d{2}) - Group 3: #.## number
END
Check:
> as.regex(pattern2)
<regex> ^([\d]+)\.([\w\W]*?)[\s]*(\d\.[\d]{2})$
See the regex demo.