在短语之前拉出文本 - Regex R

Pull out text before phrase - Regex R

我希望在 R 中使用 Regex 提取出现在一组短语之前的文本。

示例短语 c("PHRASE1", "PHRASE2", "PHRASE3")

示例文本:

*NAME ALPHA PHRASE1 BLA BLA TEXT 81249
*NAME BETA PHRASE1 BLA BLA 81229
*NAME GAMMA PHRASE2 BLA BLA TEXT 85129
*NAME DELTA PHRASE3 BLA BLA 86129
*NAME EPSILON PHRASE2 BLA BLA 81729

我想拉出下面的c("NAME ALPHA", "NAME BETA", "NAME GAMMA")等等(忽略*)。

正则表达式 101 link: https://regex101.com/r/Fzinr8/1

初次尝试

(!\*)q+(?=PHRASE1)

R中:

str_extract(x, "(!\*)q+(?=PHRASE1)")

一个stringr解决方案

您可以使用

x<-c("*NAME ALPHA PHRASE1 BLA BLA TEXT 81249","*NAME BETA PHRASE1 BLA BLA 81229","*NAME GAMMA PHRASE2 BLA BLA TEXT 85129","*NAME DELTA PHRASE3 BLA BLA 86129","*NAME EPSILON PHRASE2 BLA BLA 81729")
library(stringr)
context <- c("PHRASE1", "PHRASE2", "PHRASE3")
str_match(x, paste0("\*(.*?)\s+(?:", paste(context, collapse="|"), ")"))[,2]
# => [1] "NAME ALPHA"   "NAME BETA"    "NAME GAMMA"   "NAME DELTA"   "NAME EPSILON"

参见regex demo

详情

  • \* - 一个 * 字符
  • (.*?) - 第 1 组(在 str_match 之后使用 [,2] 访问):除换行字符外的任何零个或多个字符尽可能少
  • \s+(?:PHRASE1|PHRASE2|PHRASE3) - 1 个或多个空格和上下文字符串之一。

基础 R 解决方案:

x<-c("*NAME ALPHA PHRASE1 BLA BLA TEXT 81249","*NAME BETA PHRASE1 BLA BLA 81229","*NAME GAMMA PHRASE2 BLA BLA TEXT 85129","*NAME DELTA PHRASE3 BLA BLA 86129","*NAME EPSILON PHRASE2 BLA BLA 81729")
context <- c("PHRASE1", "PHRASE2", "PHRASE3")
pattern <- paste0("\*\K.*?(?=\s+(?:", paste(context, collapse="|"), "))")
regmatches(x, regexpr(pattern, x, perl=TRUE))
## => [1] "NAME ALPHA"   "NAME BETA"    "NAME GAMMA"   "NAME DELTA"   "NAME EPSILON"

R demo online。请注意,此方法需要 PCRE 正则表达式才能工作,因此 perl=TRUE 参数是必需的。

\K PCRE 构造忽略了当前匹配内存缓冲区中到目前为止匹配的文本。 (?=...) 构造是一个积极的前瞻性匹配字符串中的位置(这就是为什么它被称为零宽度断言),紧随其后的是前瞻性模式。

正在将我的评论转换为答案,以便未来的访问者可以轻松找到解决方案。

您可以通过后视和前视来使用此正则表达式:

str_extract(x, '(?<=\*).*?(?=\s(?:PHRASE1|PHRASE2|PHRASE3))');

RegEx Demo

正则表达式详细信息:

  • (?<=\*):断言我们在之前的位置有一个*
  • .*?:匹配0个或多个任意字符(惰性匹配)
  • (?=\s(?:PHRASE1|PHRASE2|PHRASE3)):正面前瞻断言我们在当前位置
  • 之前有一个空格后跟(?:PHRASE1|PHRASE2|PHRASE3)

替代 strsplit() 然后删除尾随空格

代码

  sapply(str2, function(z){
    # remove * and whitespaces
    gsub("[*]|\s+$", "", 
    # split by phrase and choose part of interest
    sapply(strsplit(str1, z)[grepl(z, str1)], "[[", 1))
   })
    
# $PHRASE1
# [1] "NAME ALPHA" "NAME BETA" 

# $PHRASE2
# [1] "NAME GAMMA"   "NAME EPSILON"

# $PHRASE3
# [1] "NAME DELTA"

数据

str1 <- c("*NAME ALPHA PHRASE1 BLA BLA TEXT 81249",
"*NAME BETA PHRASE1 BLA BLA 81229",
"*NAME GAMMA PHRASE2 BLA BLA TEXT 85129",
"*NAME DELTA PHRASE3 BLA BLA 86129",
"*NAME EPSILON PHRASE2 BLA BLA 81729")

str2 <- c("PHRASE1", "PHRASE2", "PHRASE3")