[R] Minimal match to regexp?

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Thu Jan 26 01:57:11 CET 2023


Thanks for pointing out my mistake.  I oversimplified the real problem.

I'll try to post a version of it that comes closer:  Suppose I have a 
string like this:

x <- "\n```html\nblah blah \n```\n\n```r\nblah blah\n```\n"

If I cat() it, I see that it is really markdown source:

   ```html
   blah blah
   ```

   ```r
   blah blah
   ```

I want to find the part that includes the html block, but not the r 
block.  So I want to match "```html", followed by a minimal number of 
characters, then "```".  Then this pattern works:

   pattern <- "\n```html\n.*?\n```\n"

and we get the right answer:

   cat(regmatches(x, regexpr(pattern, x)))

   ```html
   blah blah
   ```

Okay, but this flavour of markdown says there can be more backticks, not 
just 3.  So the block might look like

   ````html
   blah blah
   ````

I need to have the same number of backticks in the opening and closing 
marker.  So I make the pattern more complicated, and it doesn't work:

   pattern2 <- "\n([`]{3,})html\n.*?\n\\1\n"

This matches all of x:

   > pattern2 <- "\n([`]{3,})html\n.*?\n\\1\n"
   > cat(regmatches(x, regexpr(pattern2, x)))

   ```html
   blah blah
   ```

   ```r
   blah blah
   ```


Is that a bug, or am I making a silly mistake again?

Duncan Murdoch



On 25/01/2023 7:34 p.m., Andrew Simmons wrote:
> grep(value = TRUE) just returns the strings which match the pattern. You 
> have to use regexpr() or gregexpr() if you want to know where the 
> matches are:
> 
> ```
> x <- "abaca"
> 
> # extract only the first match with regexpr()
> m <- regexpr("a.*?a", x)
> regmatches(x, m)
> 
> # or
> 
> # extract every match with gregexpr()
> m <- gregexpr("a.*?a", x)
> regmatches(x, m)
> ```
> 
> You could also use sub() to remove the rest of the string: 
> `sub("^.*(a.*?a).*$", "\\1", x)`
> keeping only the match within the parenthesis.
> 
> 
> On Wed, Jan 25, 2023, 19:19 Duncan Murdoch <murdoch.duncan using gmail.com 
> <mailto:murdoch.duncan using gmail.com>> wrote:
> 
>     The docs for ?regexp say this:  "By default repetition is greedy, so
>     the
>     maximal possible number of repeats is used. This can be changed to
>     ‘minimal’ by appending ? to the quantifier. (There are further
>     quantifiers that allow approximate matching: see the TRE
>     documentation.)"
> 
>     I want the minimal match, but I don't seem to be getting it.  For
>     example,
> 
>     x <- "abaca"
>     grep("a.*?a", x, value = TRUE)
>     #> [1] "abaca"
> 
>     Shouldn't I have gotten "aba", which is the first match to "a.*a"?  If
>     not, what would be the regexp that would give me the first match to
>     "a.*a", without greedy expansion of the .*?
> 
>     Duncan Murdoch
> 
>     ______________________________________________
>     R-help using r-project.org <mailto:R-help using r-project.org> mailing list --
>     To UNSUBSCRIBE and more, see
>     https://stat.ethz.ch/mailman/listinfo/r-help
>     <https://stat.ethz.ch/mailman/listinfo/r-help>
>     PLEASE do read the posting guide
>     http://www.R-project.org/posting-guide.html
>     <http://www.R-project.org/posting-guide.html>
>     and provide commented, minimal, self-contained, reproducible code.
>



More information about the R-help mailing list