用正则表达式提取ngram

Tyl*_*ker 8 regex r stringi

Karl Broman的帖子:https://kbroman.wordpress.com/2015/06/22/randomized-hobbit-2/ 让我玩正则表达式和ngrams只是为了好玩.我试图用正则表达式提取2克.我知道有解析器可以做到这一点,但我对正则表达式逻辑感兴趣(即,这是一个我无法满足的自我挑战).

下面我给出一个最小的例子和所需的输出.我尝试的问题是2折:

  1. 克(单词)被吃掉了,下次通过时无法使用. 如何让它们可用于第二次传递?(例如,我希望在之前已被消费之后like可用)like toastI like

  2. 我无法在未捕获的单词之间创建空格(即使我使用过,也请注意输出中的尾随空格(?:\\s*)). 如何在第n个(在本例中为第二个)单词中捕获尾随空格?我知道这可以简单地完成:"(\\b[A-Za-z']+\\s)(\\b[A-Za-z']+)"对于2克但我想将解决方案扩展到n-gram.PS我知道,\\w但我不认为下划线和数字是单词部分,但请考虑'作为单词部分.

MWE:

library(stringi)

x <- "I like toast and jam."

stringi::stri_extract_all_regex(
    x,
    pattern = "((\\b[A-Za-z']+\\b)(?:\\s*)){2}"
)

## [[1]]
## [1] "I like "    "toast and "
Run Code Online (Sandbox Code Playgroud)

期望的输出:

## [[1]]
## [1] "I like"  "like toast"    "toast and"  "and jam"
Run Code Online (Sandbox Code Playgroud)

Mat*_*rde 8

这是使用基本R正则表达式的一种方法.这可以很容易地扩展到处理任意n-gram.诀窍是将捕获组置于正向前瞻断言中,例如,(?=(my_overlapping_pattern))

x <- "I like toast and jam."
pattern <- "(?=(\\b[A-Za-z']+\\b \\b[A-Za-z']+\\b))"
matches<-gregexpr(pattern, x, perl=TRUE)
# a little post-processing needed to get the capture groups with regmatches
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
regmatches(x, matches)

# [[1]]
# [1] "I like"     "like toast" "toast and"  "and jam"
Run Code Online (Sandbox Code Playgroud)