Pertanyaan Kelompok regex menangkap dalam R dengan beberapa kelompok penangkapan


Di R, apakah mungkin mengekstrak pengambilan grup dari pencocokan ekspresi reguler? Sejauh yang saya tahu, tidak ada satupun grep, grepl, regexpr, gregexpr, sub, atau gsub kembalikan tangkapan grup.

Saya perlu mengekstrak pasangan nilai-kunci dari string yang dikodekan demikian:

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

Saya selalu bisa melakukan beberapa grep pertandingan lengkap, atau melakukan pemrosesan di luar (non-R), tetapi saya berharap saya bisa melakukan semuanya dalam R. Apakah ada fungsi atau paket yang menyediakan fungsi seperti itu untuk melakukan ini?


75
2018-06-04 18:25


asal


Jawaban:


str_match(), dari stringr paket, akan melakukan ini. Ini mengembalikan matriks karakter dengan satu kolom untuk setiap grup dalam pertandingan (dan satu untuk seluruh pertandingan):

> 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"    

96
2018-04-06 03:13



gsub melakukan ini, dari contoh Anda:

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

Anda perlu melipatgandakan diri dari tanda kutip lalu mereka bekerja untuk regex.

Semoga ini membantu.


39
2018-06-04 22:44



Mencoba regmatches() dan regexec():

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

21
2018-05-15 11:32



gsub () dapat melakukan ini dan hanya mengembalikan grup capture:

Namun, agar ini berfungsi, Anda harus secara eksplisit memilih elemen di luar grup tangkapan Anda sebagaimana disebutkan dalam bantuan gsub ().

(...) elemen karakter vektor 'x' yang tidak diganti akan dikembalikan tidak berubah.

Jadi, jika teks Anda untuk dipilih terletak di tengah-tengah beberapa string, tambahkan. * Sebelum dan sesudah grup capture harus memungkinkan Anda untuk hanya mengembalikannya.

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


16
2018-04-26 21:43



Saya suka perl ekspresi reguler yang kompatibel. Mungkin orang lain juga ...

Berikut ini adalah fungsi yang melakukan perl ekspresi reguler yang kompatibel dan cocok dengan fungsi fungsi dalam bahasa lain yang saya gunakan:

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
2018-01-29 16:53



Ini adalah bagaimana saya akhirnya mengatasi masalah ini. Saya menggunakan dua regexes terpisah untuk mencocokkan grup pengambilan pertama dan kedua dan menjalankan dua gregexpr panggilan, lalu tarik substring yang cocok:

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"))

2
2018-06-05 16:06



Seperti yang disarankan di stringr paket, ini dapat dicapai menggunakan salah satunya str_match() atau str_extract().

Diadaptasi dari manual:

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})"

Mengekstrak dan menggabungkan grup kami:

str_extract(strings, phone)
# [1] "219 733 8965" "329-293-8753" NA             "239 923 8115" "579-499-7527" NA            
# [7] "543.355.3679"

Menunjukkan grup dengan matriks keluaran (kami tertarik dengan kolom 2+):

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

1
2017-12-23 15:37



Solusi dengan strcapture dari utils:

x <- c("key1 :: 0.01",
       "key2 :: 0.02")
strcapture(pattern = "(.*) :: (0\\.[0-9]+)",
           x = x,
           proto = list(key = character(), value = double()))
#>    key value
#> 1 key1  0.01
#> 2 key2  0.02

1
2017-08-24 01:22