[英]Regular expression in R extracts the part between two matching strings (NOT intendet)
我正在尝试清理R中的某些文档并提取文本引用。 如果有两个引用彼此接近(之间只有几个词),则R也会提取匹配字符串之间的部分。 这可能与我的正则表达式贪婪有关,但是我不确定该如何解决。
我的正则表达式看起来像这样
"\\([.A-Z].*\\,[[:space:]]([0-9]{4}[a-z]?)\\)|\\([.A-Z].*\\,[[:space:]][n.d.].*\\)|\\([.A-Z].*\\,[[:space:]]\\(?forthcoming\\)?\\)|\\([0-9]{4}[a-z]?\\)"
这是一些示例数据
s <- "Author (Author, 1996), Text"
t <- "Author (Author, 1996a), Text"
r <- "Author (Bla usw, forthcoming), Title Analysis, Paris"
k <- "Author (Author, n.d.), text"
m <- "text (Lara, Bera and Ceta, 2009), I dont want R to grab this part (Whatever, 2003) text goes on"
n <- "Smthing (Author, forthcoming some other text I do not want extracted because it is not a citation but some random numbers and text 1234) stmth"
n <- "Smthing (Author, forthcoming) stmth"
i <- "Authors or something, A B and C. (2012a), text,"
l <- list(s,t,r, k, m, i,n )
为了检查它是否有效,我使用了:
regmatches(l, regexpr("\\([.A-Z].*\\,[[:space:]]([0-9]{4}[a-z]?)\\)| \\([.A-Z].*\\,[[:space:]][n.d.].*\\)|\\([.A-Z].*\\,[[:space:]]\\(?forthcoming\\)?\\)|\\([0-9]{4}[a-z]?\\)", l))
我只想要括号中的部分,但只需要这一部分(文本中有更多的括号,因此我不能仅提取那些部分)。
所以我要提取
(Author, 1996)
(Author, 1996a)
(Author, n.d.)
(Lara, Bera and Ceta, 2009)
(Whatever, 2003)
(Author, forthcoming)
(2012a)
但目前它也在此处提取此字符串的中间部分。 我想要括号和其他字符串中的文本,但不希望它们之间的部分表示“我不想R抓住这一部分”。
(Lara, Bera and Ceta, 2009), I dont want R to grab this part (Whatever, 2003)
我该如何预防?
对于单线解决方案,我们可以将sub
与以下正则表达式模式结合使用:
.*?(\\([^)]+\\)).*
这表示要匹配并捕获括号中的第一项。 注意.*?
是惰性点,它告诉正则表达式引擎在第一次出现时停止。
这是一个示例脚本:
m <- "text (Lara, Bera and Ceta, 2009), I dont want R to grab this part (Whatever, 2003) text goes on"
sub(".*?(\\([^)]+\\)).*", "\\1", m)
[1] "(Lara, Bera and Ceta, 2009)"
这不是完美的,但您可以使用
## Input
l <- c("Author (Author, 1996), Text", "Author (Author, 1996a), Text", "Author (Bla usw, forthcoming), Title Analysis, Paris", "Author (Author, n.d.), text", "text (Lara, Bera and Ceta, 2009), I dont want R to grab this part (Whatever, 2003) text goes on", "Authors or something, A B and C. (2012a), text,", "Smthing (Author, forthcoming) stmth")
## Building the regex...
author_rx <- "\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*"
must_have_rx <- "(?:[0-9]{4}[a-z]?|forthcoming|n\\.d\\.)"
regex <- paste0("\\((?:",author_rx,"(?:\\s*(?:and|,)\\s*",author_rx, ")*\\s*(?:,\\s*)?)?\\b",must_have_rx,"\\)")
## Running the regex...
str_extract_all(l, regex)
结果:
[[1]]
[1] "(Author, 1996)"
[[2]]
[1] "(Author, 1996a)"
[[3]]
character(0)
[[4]]
[1] "(Author, n.d.)"
[[5]]
[1] "(Lara, Bera and Ceta, 2009)" "(Whatever, 2003)"
[[6]]
[1] "(2012a)"
[[7]]
[1] "(Author, forthcoming)"
正则表达式是
\((?:\p{Lu}\w*(?:\s+\p{Lu}\w*)*(?:\s*(?:and|,)\s*\p{Lu}\w*(?:\s+\p{Lu}\w*)*)*\s*(?:,\s*)?)?\b(?:[0-9]{4}[a-z]?|forthcoming|n\.d\.)\)
参见regex演示 。
细节
\\(
- (
字符 (?:
-开始一个可选的非捕获组:
\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*
- author_rx
:一个大写字母,0个单词字符,然后0个或多个序列,包含1+个空格,1个大写字母和0+字字符 (?:\\s*(?:and|,)\\s*\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*)*
-0个或多个序列:
\\s*
-0+空格 (?:and|,)
- and
或,
\\s*
-0+空格 \\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*
- author_rx
模式(请参见上文) \\s*
-0+空格 (?:,\\s*)?
- ,
和0+空格的可选序列 )?
-第一个非捕获组的结尾 \\b
单词边界 (?:[0-9]{4}[az]?|forthcoming|n\\.d\\.)
-以下之一:
[0-9]{4}[az]?
-四位数和一个可选的小写字母 forthcoming
-这个词 n\\.d\\.
nd
子串 \\)
-a )
字符。 如果在括号中显示了您不希望匹配但在没有括号的情况下提取字符串的所有示例,将很有帮助。 然后,您可以使用自己喜欢的任何复杂模式从想要的代码中删除这些代码,而不必担心括号中没有垃圾。 (例如,如果只有好的数字有4位数字或逗号,则应用grep(",|\\\\d{4}", s, value = TRUE)
。
library(gsubfn)
s <- unlist(strapplyc(unlist(l), "\\([^)]*\\)"))
给出以下内容:
> s
[1] "(Author, 1996)"
[2] "(Author, 1996a)"
[3] "(Bla usw, forthcoming)"
[4] "(Author, n.d.)"
[5] "(Lara, Bera and Ceta, 2009)"
[6] "(Whatever, 2003)"
[7] "(Author, forthcoming some other text 1234)"
[8] "(Author, forthcoming)"
[9] "(2012a)"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.