PHP preg_match_all的等效函数

3

我正在寻找一个与PHP的 preg_match_all 函数等效的 R 语言函数。

目标:

  • 搜索单个字符串(而非多个字符串的向量)以查找正则表达式模式
  • 返回匹配结果矩阵

示例:

假设存在以下不带定界符的字符串。

"This is a sample string written like a paragraph. In this string two sets of information exist. Each set contains two variables. We want to extract the sets and variables within those sets. Each information set is formatted the same way. The first set is Title: Sir; Last Name: John; and the second set is Title: Mr.; Last Name: Smith."

使用类似于以下正则表达式模式:

"Title: ([^;]*?); Last Name: ([^;.]*?)"

我希望能够从上述字符串中生成以下矩阵:
[  ][,1]  [,2]
[1,] Sir  John
[2,] Mr.  Smith

我已经成功地在远程服务器上使用preg_match_all函数完成了这个任务,但我要访问的文本文件相对较大(不是非常大,但上传速度比较慢)。在R中构建将节省大量时间。
我已阅读有关在R中使用grep等的内容,但我找到的每个例子都是在向量中搜索模式,而我无法生成如上所述的矩阵。
我也试过stringr包,但同样没有成功生成矩阵。
这对我来说似乎是一项常见任务,所以我相信比我聪明的人已经找到了解决方案。

1
这是一个相当明确定义的问题;您可以从 stringr::str_extract_all (使用正则表达式 "Title: ([^;]*) and Last Name: ([^;. ]*)") 开始,然后使用 strsplit,但是您指定的正则表达式并不完全匹配 "Title: Mr.; Last Name: Smith" ... - Ben Bolker
在开始时,您的模式是错误的。(?i)Title: ([^;]*)(?:;| and) Last Name: ([^;.]*) 似乎符合您的要求。 - Casimir et Hippolyte
你说得对,我改变了示例字符串,但忘记更新正则表达式。我现在已经纠正了这个问题。 - AWaddington
3个回答

4
考虑以下使用regmatches选项:

使用regmatches选项:

x <- 'This is a sample string written like a paragraph. In this string two sets of information exist. Each set contains two variables. We want to extract the sets and variables within those sets. Each information set is formatted the same way. The first set is Title: Sir; Last Name: John; and the second set is Title: Mr.; Last Name: Smith.'
m <- regmatches(x, gregexpr('(?i)Title: \\K[^;]+|Last Name: \\K[^;.]+', x, perl=T))
matrix(unlist(m), ncol=2, byrow=T)

输出:

     [,1]  [,2]   
[1,] "Sir" "John" 
[2,] "Mr." "Smith"

+1(来自之前的评论),不得不查找\K,真的很有趣。回来评论一下,你可能不需要捕获括号,但看起来你已经考虑到了这一点! - BrodieG
@BrodieG 是的,我忘记把它们拿出来了。 - hwnd

2
由于某种原因,似乎没有一种简单的方法在基础中提取捕获的匹配项(我希望regmatches也能与捕获组一起使用,但它不支持)。我最终编写了自己的代码,你可以在regcapturedmatches.R找到它。它可以与以下文本一起使用:

a <- "第一个集合是Title:Sir和Last Name:John;第二个集合是Title:Mr.和Last Name:Smith。"

m<-gregexpr("Title: ([^;]*) and Last Name: ([^;.]*)", a, perl=T, ignore.case=T)
regcapturedmatches(a,m)[[1]]

这将返回结果。
     [,1]  [,2]   
[1,] "Sir" "John" 
[2,] "Mr." "Smith"

我在[[1]]处添加了文字,因为你说一次只能处理一个字符串。该函数可以处理向量,并将结果返回到列表中。事实上,在R中,每个东西都是向量,因此没有所谓的“单个”字符串,你只有一个长度为1的字符串向量。

当然,这种方法仅与你的正则表达式一样好。我不得不稍微修改你的示例数据,以便你的表达式匹配更多的标题/名称。


有一种方法可以获取匹配的结果(regexec + regmatches),但只能获取第一个匹配。stringr 中的 str_match_all 会重复使用上述方法来模拟 gregexec 的功能,如果它存在的话。 - BrodieG

2
这里是一个关于 stringr 的版本:
library(stringr)
str_match_all(x, pattern)

生成:

[[1]]
     [,1]                              [,2]  [,3]   
[1,] "Title: Sir and Last Name: John"  "Sir" "John" 
[2,] "Title: Mr. and Last Name: Smith" "Mr." "Smith"

请注意,我必须编辑您的文本,以便第二个文本也以“和姓:”的形式出现。要获取您的矩阵,您只需执行以下操作: 请留意,我已经编辑了您的文本,使第二个格式也是“名字+姓氏:”。如果您想获取您的矩阵,只需要执行以下操作:
result[[1]][[-1]]  # assumes the above is in `result`

这种方法的一个限制是它使用regexec,不支持perl正则表达式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接