Можно ли в R извлечь групповой захват из совпадения регулярного выражения? Насколько я могу судить, ни один из grep
, grepl
, regexpr
, gregexpr
, sub
, или gsub
вернуть снимки группы.
Мне нужно извлечь пары ключ-значение из строк, которые закодированы таким образом:
\((.*?) :: (0\.[0-9]+)\)
Я всегда могу просто выполнить несколько полных совпадений grep или выполнить некоторую внешнюю (не R) обработку, но я надеялся, что смогу сделать все это в R. Есть ли функция или пакет, который предоставляет такую функцию для этого?
regex
r
capture
capture-group
Дэниел Дикисон
источник
источник
str_match_all()
сопоставить все группы в регулярном выражении[,1]
Полное совпадение.[,2:3]
это захваченные группы.gsub делает это из вашего примера:
gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
вам нужно дважды экранировать \ s в кавычках, тогда они работают для регулярного выражения.
Надеюсь это поможет.
источник
gsub
Странице R очень нужен пример, показывающий, что вам нужно '\\ 1', чтобы избежать ссылки на группу захвата.Попробуйте
regmatches()
иregexec()
:regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)")) [[1]] [1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
источник
regmatches
чего я никогда раньше не виделregexec
возвращает список, содержащий информацию только о местоположении совпадений, поэтомуregmatches
от пользователя требуется указать строку, к которой принадлежит список совпадений.gsub () может это сделать и вернуть только группу захвата:
Однако для того, чтобы это работало, вы должны явно выбрать элементы за пределами вашей группы захвата, как указано в справке gsub ().
Поэтому, если ваш текст, который нужно выделить, находится в середине некоторой строки, добавление. * До и после группы захвата должно позволить вам только вернуть его.
gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
источник
Мне нравятся регулярные выражения, совместимые с Perl. Наверное, кто-то другой тоже ...
Вот функция, которая выполняет регулярные выражения, совместимые с 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 }
источник
Вот как я решил решить эту проблему. Я использовал два отдельных регулярных выражения для сопоставления первой и второй групп захвата и
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"))
источник
expr "xyx0.0023xyxy" : '[^0-9]*\([.0-9]\+\)'
Решение с
strcapture
помощью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
источник
Как указывается в
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"
источник
_all
суффикса для соответствующихstringr
функций.Это можно сделать с помощью пакета unglue , взяв пример из выбранного ответа:
# 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, необязательно с именованным захватом:
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
источник