我正在努力更深入地学习R中的正则表达式.我给了自己一些我认为不容易理解的简单任务.我想提取所有4个字母的单词.在这四个字母的单词中我想忽略(不要算)撇号.我可以在没有正则表达式的情况下执行此操作但需要正则表达式解决方案 这是一个MWE和我尝试过的:
text.var <- "This Jon's dogs' 'bout there in Mike's re'y word."
pattern <- "\\b[A-Za-z]{4}\\b(?!')"
pattern <- "\\b[A-Za-z]{4}\\b|\\b[A-Za-z']{5}\\b"
regmatches(text.var, gregexpr(pattern, text.var, perl = TRUE))
Run Code Online (Sandbox Code Playgroud)
**期望的输出:**
[[1]]
[1] "This" "Jon's" "dogs'" "'bout" "word"
Run Code Online (Sandbox Code Playgroud)
我认为第二种模式可行,但它也会抓取包含5个字符的单词.
hwn*_*wnd 16
这是一个很有挑战性的问题,这是一个棘手的答案.
> x <- "This Jon's dogs' 'bout there in Mike's re'y word."
> re <- "(?i)('?[a-z]){5,}(*SKIP)(?!)|('?[a-z]){4}'?"
> regmatches(x, gregexpr(re, x, perl=T))[[1]]
## [1] "This" "Jon's" "dogs'" "'bout" "word"
Run Code Online (Sandbox Code Playgroud)
说明:
想法是跳过由5个或更多字母字符和可选撇号组成的任何单词模式.
在交替运算符的左侧,我们匹配我们不想要的子模式.使其失败并强制正则表达式引擎不使用回溯控制重试子字符串.如下所述:
(*SKIP) # advances to the position in the string where (*SKIP) was
# encountered signifying that what was matched leading up
# to cannot be part of the match
(?!) # equivalent to (*FAIL), causes matching failure,
# forcing backtracking to occur
Run Code Online (Sandbox Code Playgroud)
交替操作员的右侧符合我们想要的......
从本质上讲,简单来说就是使用丢弃技术.
(?:'?[a-z]){5,}|((?:'?[a-z]){4}'?)
Run Code Online (Sandbox Code Playgroud)
你可以在上下文中使用交替运算符,将你要排除的内容放在左边(说丢掉它,它是垃圾)并在右侧的捕获组中放置你想要匹配的内容.
Cas*_*yte 11
您可以使用此模式:
(?i)(?<![a-z'])(?:'?[a-z]){4}'?(?![a-z'])
Run Code Online (Sandbox Code Playgroud)
你可以使用discard技术并使用这样的正则表达式:
\b\w{0,2}\b(?:'\w)?|\b\w{3}(?!')\b|\b\w{5,}\b|('?\b\w+\b'?\w?)
Run Code Online (Sandbox Code Playgroud)
MATCH 1
1. [0-4] `This`
MATCH 2
1. [5-10] `Jon's`
MATCH 3
1. [11-16] `dogs'`
MATCH 4
1. [17-22] `'bout`
MATCH 5
1. [32-36] `word`
Run Code Online (Sandbox Code Playgroud)
对于R,需要转义特殊字符.
正如您在正则表达式模式中所看到的那样,您可以在模式的左侧使用您不想要的任何内容,并将您真正想要的内容留在最右侧的捕获组中.丢弃技术背后的想法是:
discard this|don't want this|still don't care this|(Oh yeah! I grab this)
Run Code Online (Sandbox Code Playgroud)
感谢到EdConttrell和johnwait帮助我提高了答案.
编辑两次:(感谢hex494D49):
(?i)(?<=\W|^)(?<!')'*(?:\w{4}|\w'*\w{3}|\w{2}'*\w{2}|\w{3}'*\w|\w{2}'*\w'*\w|\w'*\w{2}'*\w|\w'*\w'*\w{2}|\w'*\w'*\w'*\w)'*(?!')(?=\W|$)
更好地适应所有可能的情况......
但是,问题的标题是:
grab n letter words don't count apostrophes regex
Run Code Online (Sandbox Code Playgroud)
所以我不推荐我的解决方案.