Pergunta

Em R, é possível extrair captura de grupo a partir de uma expressão regular? Tanto quanto eu posso dizer, nenhum dos grep, grepl, regexpr, gregexpr, sub, ou gsub voltar a captura do grupo.

Eu preciso extrair pares chave-valor de cordas que são codificados assim:

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

Eu sempre pode apenas fazer várias greps full-jogo, ou fazer algum processamento externo (não-R), mas eu estava esperando que eu possa fazer tudo dentro R. Existe uma função ou um pacote que fornece tal função para fazer isso?

Outras dicas

gsub faz isso, a partir do seu exemplo:

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

você precisa dobrar escapar o \ s nas citações em seguida, eles trabalham para a regex.

Espero que isso ajude.

regmatches() Experimente e regexec():

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

gsub () pode fazer isso e retornar somente o grupo de captura:

No entanto, para que isso funcione, você deve selecionar explicitamente elementos fora do seu grupo de captura, como mencionado na ajuda gsub ().

(...) elementos de caráter vetores 'x' que não são substituídos serão devolvidos inalterada.

Portanto, se seu texto a ser selecionado mentiras no meio de alguma corda, acrescentando. * Antes e depois do grupo de captura deve permitir que você devolvê-lo apenas.

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

Eu gosto de expressões regulares compatíveis com Perl. Provavelmente alguém faz também ...

Aqui está uma função que faz perl expressões regulares compatíveis e combina a funcionalidade de funções em outras línguas que eu estou acostumado a:

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
}

Isto é como eu acabei trabalhando em torno deste problema. Eu usei duas expressões regulares separadas para coincidir com o primeiro e segundo grupos de captura e executar duas chamadas gregexpr, em seguida, puxe os substrings correspondentes:

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

Solução com strcapture do 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
scroll top