R中的正则表达式提取两个匹配字符串之间的部分(非intendet)

R中的正则表达式提取两个匹配字符串之间的部分(非intendet),r,regex,nlp,R,Regex,Nlp,我试图清理一些R中的文档,并提取文本引用。如果有两个相互接近的引用(中间只有几个单词),R也会提取匹配字符串之间的部分。这可能与我的正则表达式贪婪有关,但我不知道如何解决这个问题 我的正则表达式看起来像这样 "\\([.A-Z].*\\,[[:space:]]([0-9]{4}[a-z]?)\\)|\\([.A-Z].*\\,[[:space:]][n.d.].*\\)|\\([.A-Z].*\\,[[:space:]]\\(?forthcoming\\)?\\)|\\([0-9]{4}[a-z

我试图清理一些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 )
我只想要括号中的部分,但只想要这个(文本中有更多的括号,所以我不能只提取它们)

所以我想把它提取出来

(Author, 1996)
(Author, 1996a)
(Author, n.d.)
(Lara, Bera and Ceta, 2009)
(Whatever, 2003)
(Author, forthcoming)
(2012a)
但它现在也提取了这个字符串的中间部分。我想要两个括号中的文本以及其他字符串中的文本,但不要它们之间的部分,即“我不想让R抓住这部分”


如何防止这种情况发生?

对于单行程序解决方案,我们可以将
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)"

m如果您在括号中显示不希望匹配的字符串示例,但在没有该示例的情况下提取括号中的所有部分,这将非常有用然后你可以使用你喜欢的复杂模式从中筛选出你想要的,而不必担心括号中没有的垃圾。(例如,如果只有好的有4位数字或逗号,那么应用
grep(,| \\d{4}),s,value=TRUE)


它并不完美,但您可以使用

## 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)
正则表达式是

\((?:\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\.)\)

详细信息

  • \(
    -
    char
  • (?:
    -启动可选的非捕获组:
    • \p{Lu}\w*(?:\s+\p{Lu}\w*)*
      -
      作者_rx
      :一个大写字母,0+单词字符,然后是0个或多个1+空格、1个大写字母和0+单词字符序列
    • (?:\s*(?:和|,)\s*\p{Lu}\w*(?:\s+\p{Lu}\w*)*)*
      -0或更多序列:
      • \s*
        -0+空格
      • (?:和|,)
        -
      • \s*
        -0+空格
      • \p{Lu}\w*(?:\s+\p{Lu}\w*)*
        -
        作者接收模式(见上文)
  • \s*
    -0+空格
  • (?:,\s*)?
    -可选的
    和0+空格序列
  • )?
    -第一个非捕获组的结束
  • \b
    -单词边界
  • (?:[0-9]{4}[a-z]?|即将推出| n\.d\)
    -其中一个:
    • [0-9]{4}[a-z]?
      -四位数字和一个可选的小写字母
    • 即将推出
      -这个词
    • n\.d\.
      -
      n.d.
      子字符串
  • \)
    -a
    字符

这只是抓住了我脚本中的所有字符串。您的示例输入/输出似乎暗示您希望保留括号中的第一个术语,而不是第二个术语。如果不是这样,请用实际问题更新您的问题。@H.Stevens,并说明答案实际失败的地方。(很抱歉,如果我用错了这个工具,我以前从来没有见过它)你可能想要
stru extract\u all(l,“\([^()]*\”)
不幸的是,这也会抓住我在分析中想要的括号中的文本…可能
unlist(str\u extract\u all(l,”([^()]*\\b(?[0-9]{4}[a-z]?(即将推出的[n\\\\.d\\)))”)
?你想要
(Bla usw,即将发布)
还是不?不,我不想这样,因为它可能是一些重要的文本(如果它抓住了“即将发布”这个词,那很好,我只是想看看我是否有这个词。这是因为匹配名称与正则表达式太难了。我现在必须去,尝试
取消列表(stru extract\u all(l),\(?:\\p{Lu}\\w*(?:\\s+\\p{Lu Lu)\\w*)*(?:\\s*(?:and |,)\\s*\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*\\s*(?:,\\s*)?\\b(?[0-9]{4}[a-z]?(?:即将推出的\\\.d\\)\)
,请参阅。不幸的是,这也抓住了我在分析中想要的括号中的文本。模式是相同的,但解决方案只提取了第一行引用。
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)"         
## 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\.)\)