रेगेक्स ग्रुप कैप्चर आर में कई कैप्चर-ग्रुप्स के साथ


94

आर में, क्या एक नियमित अभिव्यक्ति मैच से ग्रुप कैप्चर को निकालना संभव है? जहाँ तक मुझे बता के रूप में कर सकते हैं, में से कोई भी grep, grepl, regexpr, gregexpr, sub, या gsubसमूह कैप्चर लौट आते हैं।

मुझे इस तरह एन्कोड किए गए स्ट्रिंग्स से की-वैल्यू पेयर निकालने की जरूरत है:

\((.*?) :: (0\.[0-9]+)\)

मैं हमेशा केवल कई पूर्ण-मिलान ग्रीप्स कर सकता हूं, या कुछ बाहर (गैर-आर) प्रसंस्करण कर सकता हूं, लेकिन मुझे उम्मीद थी कि मैं आर के भीतर यह सब कर सकता हूं। क्या कोई फ़ंक्शन या पैकेज है जो ऐसा करने के लिए ऐसा फ़ंक्शन प्रदान करता है?

जवाबों:


118

str_match(), stringrपैकेज से, यह करेंगे। यह मैच में प्रत्येक समूह के लिए एक कॉलम के साथ एक वर्ण मैट्रिक्स देता है (और पूरे मैच के लिए एक):

> s = c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
> str_match(s, "\\((.*?) :: (0\\.[0-9]+)\\)")
     [,1]                         [,2]       [,3]          
[1,] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
[2,] "(moretext :: 0.111222)"     "moretext" "0.111222"    

1
और str_match_all()एक
रेगीक्स

मैं केवल [, 1] के लिए केवल पकड़े गए समूहों को कैसे प्रिंट कर सकता हूं?
नेनूर

नहीं जानते क्या ढूंढ रहे हैं। पकड़े गए समूह कॉलम 2 और 3 हैं [,1]। पूरा मैच है। [,2:3]कब्जा कर लिया समूह है।
केंट जॉनसन

50

gsub ऐसा करता है, आपके उदाहरण से:

gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"

आपको उद्धरण में फिर से भागना होगा, फिर वे रेगेक्स के लिए काम करेंगे।

उम्मीद है की यह मदद करेगा।


वास्तव में मुझे डेटा.फ्रेम में डालने के लिए कैप्चर किए गए सबस्ट्रिंग को बाहर निकालने की आवश्यकता है। लेकिन, आपके उत्तर को देखते हुए, मुझे लगता है कि मैं चेन gsub और strsplit का एक जोड़ा प्राप्त कर सकता हूं जो मुझे चाहिए, शायद: strsplit (strsplit (gsub (regex, "" \\ 1 ::\ 2 :::: ", str) ), "::::" ") [[1]]," :: ")
डैनियल डिकसन

8
महान। R gsubमैनपेज को बहुत बुरी तरह से एक उदाहरण की आवश्यकता होती है, जिसमें आपको कैप्चर-ग्रुप संदर्भ से बचने के लिए '\\ 1' की आवश्यकता होती है।
15

33

कोशिश करो regmatches()और regexec():

regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext"                   "0.1231313213"

3
वेनिला आर समाधान के लिए धन्यवाद और यह इंगित करने के लिए regmatchesकि मैंने पहले कभी नहीं देखा है
एंडी

आपको दो बार स्ट्रिंग क्यों लिखना होगा?
स्टेफानो बोरीनी

@StefanoBorini regexecकेवल मैचों के स्थान के बारे में जानकारी रखने वाली एक सूची देता है, इसलिए regmatchesउपयोगकर्ता को उस स्ट्रिंग सूची प्रदान करने की आवश्यकता होती है जो मैच सूची से संबंधित थी।
आरटीबार्ड

19

gsub () ऐसा कर सकता है और केवल कैप्चर समूह लौटा सकता है:

हालाँकि, इस कार्य के लिए, आपको स्पष्ट रूप से अपने कैप्चर समूह के बाहर के तत्वों का चयन करना होगा जैसा कि gsub () मदद में वर्णित है।

(...) वर्ण वैक्टर 'x' के तत्व जिन्हें प्रतिस्थापित नहीं किया गया है उन्हें अपरिवर्तित लौटाया जाएगा।

इसलिए यदि आपका पाठ चयनित होना चाहिए, तो कुछ स्ट्रिंग के बीच में, जोड़ने वाले समूह के पहले और बाद में आपको केवल इसे वापस करने की अनुमति देनी चाहिए।

gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"


4

मुझे perl संगत नियमित अभिव्यक्ति पसंद है। शायद कोई और भी करता है ...

यहां एक फ़ंक्शन है जो संगत नियमित अभिव्यक्तियों को करता है और अन्य भाषाओं में उन कार्यों की कार्यक्षमता से मेल खाता है जिनका मैं उपयोग करता हूं:

regexpr_perl <- function(expr, str) {
  match <- regexpr(expr, str, perl=T)
  matches <- character(0)
  if (attr(match, 'match.length') >= 0) {
    capture_start <- attr(match, 'capture.start')
    capture_length <- attr(match, 'capture.length')
    total_matches <- 1 + length(capture_start)
    matches <- character(total_matches)
    matches[1] <- substr(str, match, match + attr(match, 'match.length') - 1)
    if (length(capture_start) > 1) {
      for (i in 1:length(capture_start)) {
        matches[i + 1] <- substr(str, capture_start[[i]], capture_start[[i]] + capture_length[[i]] - 1)
      }
    }
  }
  matches
}

3

इस तरह मैंने इस समस्या के आसपास काम करना समाप्त कर दिया। मैंने पहले और दूसरे कैप्चर समूहों से मिलान करने और दो gregexprकॉल चलाने के लिए दो अलग-अलग रीजेक्स का उपयोग किया , फिर मिलान किए गए सबस्ट्रिंग्स को बाहर निकालें:

regex.string <- "(?<=\\().*?(?= :: )"
regex.number <- "(?<= :: )\\d\\.\\d+"

match.string <- gregexpr(regex.string, str, perl=T)[[1]]
match.number <- gregexpr(regex.number, str, perl=T)[[1]]

strings <- mapply(function (start, len) substr(str, start, start+len-1),
                  match.string,
                  attr(match.string, "match.length"))
numbers <- mapply(function (start, len) as.numeric(substr(str, start, start+len-1)),
                  match.number,
                  attr(match.number, "match.length"))

एक काम कोड के लिए +1। हालाँकि, मैं आर से एक त्वरित शेल कमांड expr "xyx0.0023xyxy" : '[^0-9]*\([.0-9]\+\)'
चलाऊंगा और


2

जैसा कि stringrपैकेज में सुझाया गया है, इसे str_match()या तो उपयोग करके प्राप्त किया जा सकता है str_extract()

मैनुअल से अनुकूलित:

library(stringr)

strings <- c(" 219 733 8965", "329-293-8753 ", "banana", 
             "239 923 8115 and 842 566 4692",
             "Work: 579-499-7527", "$1000",
             "Home: 543.355.3679")
phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})"

हमारे समूह निकालना और संयोजन करना:

str_extract_all(strings, phone, simplify=T)
#      [,1]           [,2]          
# [1,] "219 733 8965" ""            
# [2,] "329-293-8753" ""            
# [3,] ""             ""            
# [4,] "239 923 8115" "842 566 4692"
# [5,] "579-499-7527" ""            
# [6,] ""             ""            
# [7,] "543.355.3679" ""   

आउटपुट मैट्रिक्स के साथ समूहों को इंगित करना (हम कॉलम 2+ में रुचि रखते हैं):

str_match_all(strings, phone)
# [[1]]
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "219 733 8965" "219" "733" "8965"
# 
# [[2]]
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "329-293-8753" "329" "293" "8753"
# 
# [[3]]
#      [,1] [,2] [,3] [,4]
# 
# [[4]]
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "239 923 8115" "239" "923" "8115"
# [2,] "842 566 4692" "842" "566" "4692"
# 
# [[5]]
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "579-499-7527" "579" "499" "7527"
# 
# [[6]]
#      [,1] [,2] [,3] [,4]
# 
# [[7]]
#      [,1]           [,2]  [,3]  [,4]  
# [1,] "543.355.3679" "543" "355" "3679"

842 566 4692 के बारे में क्या
फेरो

चूक को पकड़ने के लिए धन्यवाद। _allप्रासंगिक stringrकार्यों के लिए प्रत्यय का उपयोग करके ठीक किया गया ।
मेगेट्रोन

0

यह पैकेज अनलॉग का उपयोग करके किया जा सकता है , चयनित उत्तर से उदाहरण लेते हुए:

# install.packages("unglue")
library(unglue)

s <- c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
unglue_data(s, "({x} :: {y})")
#>          x            y
#> 1 sometext 0.1231313213
#> 2 moretext     0.111222

या डेटा फ्रेम से शुरू हो रहा है

df <- data.frame(col = s)
unglue_unnest(df, col, "({x} :: {y})",remove = FALSE)
#>                          col        x            y
#> 1 (sometext :: 0.1231313213) sometext 0.1231313213
#> 2     (moretext :: 0.111222) moretext     0.111222

आप कच्चे रीगेक्स को अनलॉग पैटर्न से प्राप्त कर सकते हैं, वैकल्पिक रूप से नामित कैप्चर के साथ:

unglue_regex("({x} :: {y})")
#>             ({x} :: {y}) 
#> "^\\((.*?) :: (.*?)\\)$"

unglue_regex("({x} :: {y})",named_capture = TRUE)
#>                     ({x} :: {y}) 
#> "^\\((?<x>.*?) :: (?<y>.*?)\\)$"

अधिक जानकारी: https://github.com/moodymudskipper/unglue/blob/master/README.md

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.