Di R, apakah mungkin untuk mengekstrak tangkapan grup dari pencocokan ekspresi reguler? Sejauh yang saya tahu, tidak ada grep
, grepl
, regexpr
, gregexpr
, sub
, atau gsub
mengembalikan menangkap kelompok.
Saya perlu mengekstrak pasangan nilai kunci dari string yang dikodekan sebagai berikut:
\((.*?) :: (0\.[0-9]+)\)
Saya selalu dapat melakukan beberapa grep pertandingan penuh, atau melakukan beberapa pemrosesan di luar (non-R), tetapi saya berharap saya dapat melakukan semuanya dalam R. Apakah ada fungsi atau paket yang menyediakan fungsi seperti itu untuk melakukan ini?
regex
r
capture
capture-group
Daniel Dickison
sumber
sumber
str_match_all()
untuk mencocokkan semua grup dalam regex[,1]
adalah pertandingan penuh.[,2:3]
adalah kelompok yang ditangkap.gsub melakukan ini, dari contoh Anda:
gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
Anda perlu meloloskan diri dua kali dari \ s dalam tanda kutip lalu berfungsi untuk regex.
Semoga ini membantu.
sumber
gsub
manual R sangat membutuhkan contoh yang menunjukkan bahwa Anda memerlukan '\\ 1' untuk keluar dari referensi grup tangkap.Coba
regmatches()
danregexec()
:regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)")) [[1]] [1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
sumber
regmatches
yang belum pernah saya lihat sebelumnyaregexec
mengembalikan daftar yang menyimpan informasi hanya mengenai lokasi pertandingan, oleh karena ituregmatches
mengharuskan pengguna untuk menyediakan string milik daftar pertandingan.gsub () bisa melakukan ini dan hanya mengembalikan grup tangkapan:
Namun, agar ini berfungsi, Anda harus secara eksplisit memilih elemen di luar grup tangkapan Anda seperti yang disebutkan di bantuan gsub ().
Jadi jika teks Anda yang akan dipilih terletak di tengah-tengah beberapa string, menambahkan. * Sebelum dan sesudah grup pengambilan seharusnya memungkinkan Anda untuk hanya mengembalikannya.
gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
sumber
Saya suka ekspresi reguler yang kompatibel dengan perl. Mungkin orang lain juga melakukannya ...
Berikut adalah fungsi yang kompatibel dengan perl dan cocok dengan fungsi fungsi dalam bahasa lain yang biasa 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 }
sumber
Beginilah akhirnya saya mengatasi masalah ini. Saya menggunakan dua regex terpisah untuk mencocokkan grup tangkapan pertama dan kedua dan menjalankan dua
gregexpr
panggilan, lalu mengeluarkan 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"))
sumber
expr "xyx0.0023xyxy" : '[^0-9]*\([.0-9]\+\)'
Solusi dengan
strcapture
dariutils
: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
sumber
Seperti yang disarankan dalam
stringr
paket, ini dapat dicapai dengan menggunakan salah satustr_match()
ataustr_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_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" ""
Grup penunjuk dengan matriks keluaran (kami tertarik pada kolom 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"
sumber
_all
sufiks untukstringr
fungsi yang relevan .Ini bisa dilakukan dengan menggunakan package unglue , mengambil contoh dari jawaban yang dipilih:
# 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
Atau mulai dari bingkai data
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
Anda bisa mendapatkan regex mentah dari pola unglue, secara opsional dengan bernama capture:
unglue_regex("({x} :: {y})") #> ({x} :: {y}) #> "^\\((.*?) :: (.*?)\\)$" unglue_regex("({x} :: {y})",named_capture = TRUE) #> ({x} :: {y}) #> "^\\((?<x>.*?) :: (?<y>.*?)\\)$"
Info lebih lanjut: https://github.com/moodymudskipper/unglue/blob/master/README.md
sumber