У меня есть строка символов, а информация о том, что извлекать, заключена в круглые скобки. В настоящее время я могу извлечь информацию из последней скобки с помощью приведенного ниже кода. Как мне сделать так, чтобы он извлекал несколько скобок и возвращался как вектор?
j <- "What kind of cheese isn't your cheese? (wonder) Nacho cheese! (groan) (Laugh)"
sub("\\).*", "", sub(".*\\(", "", j))
Текущий вывод:
[1] "Laugh"
Желаемый результат:
[1] "wonder" "groan" "Laugh"
Я думаю, что есть три простых способа извлечения нескольких групп захвата в R (без использования замещения); str_match_all
, str_extract_all
и regmatches/gregexpr
комбо.
Мне нравится регулярное выражение @ kohske, которое ищет открытую скобку ?<=\\(
, ищет закрывающую скобку ?=\\)
и захватывает все в середине (лениво) .+?
, другими словами (?<=\\().+?(?=\\))
Использование того же регулярного выражения:
str_match_all
возвращает ответ в виде матрицы .
str_match_all(j, "(?<=\\().+?(?=\\))")
[,1]
[1,] "wonder"
[2,] "groan"
[3,] "Laugh"
# Subset the matrix like this....
str_match_all(j, "(?<=\\().+?(?=\\))")[[1]][,1]
[1] "wonder" "groan" "Laugh"
str_extract_all
возвращает ответ в виде списка .
str_extract_all(j, "(?<=\\().+?(?=\\))")
[[1]]
[1] "wonder" "groan" "Laugh"
#Subset the list...
str_extract_all(j, "(?<=\\().+?(?=\\))")[[1]]
[1] "wonder" "groan" "Laugh"
regmatches/gregexpr
также возвращает ответ в виде списка . Так как это базовый вариант R, некоторые люди предпочитают его. Обратите внимание на рекомендованный perl = TRUE
.
regmatches(j, gregexpr( "(?<=\\().+?(?=\\))", j, perl = T))
[[1]]
[1] "wonder" "groan" "Laugh"
#Subset the list...
regmatches(j, gregexpr( "(?<=\\().+?(?=\\))", j, perl = T))[[1]]
[1] "wonder" "groan" "Laugh"
Надеюсь, Сообщество исправит / отредактирует этот ответ, если я неправильно определил наиболее популярные варианты.
Используя пакет stringr, мы можем немного уменьшить это.
library(stringr)
# Get the parenthesis and what is inside
k <- str_extract_all(j, "\\([^()]+\\)")[[1]]
# Remove parenthesis
k <- substring(k, 2, nchar(k)-1)
@kohske использует соответствия, но в настоящее время я использую 2.13, поэтому в данный момент у меня нет доступа к этой функции. Это добавляет зависимость от stringr, но я думаю, что с ней немного легче работать, а код немного понятнее (ну ... так же ясно, как можно использовать регулярные выражения ...)
Правка может также попробовать что-то вроде этого -
re <- "\\(([^()]+)\\)"
gsub(re, "\\1", str_extract_all(j, re)[[1]])
Этот работает, определяя отмеченное подвыражение внутри регулярного выражения. Он извлекает все, что соответствует регулярному выражению, а затем gsub извлекает только часть внутри подвыражения.