#regex #r #matrix
#регулярное выражение #r #матрица
Вопрос:
Я ищу R, эквивалентный preg_match_all
функции PHP.
Цель:
- Поиск шаблона регулярного выражения в одной строке (не в векторе из нескольких строк)
- Возвращает матрицу совпадений
Пример:
Предположим, что следующая плоская строка без разграничения.
«Это пример строки, написанной как абзац. В этой строке существует два набора информации. Каждый набор содержит две переменные. Мы хотим извлечь наборы и переменные внутри этих наборов. Каждый информационный набор форматируется одинаково. Первый набор — это титул: сэр; Фамилия: Джон; а второй набор — титул: мистер; Фамилия: Смит. «
Используя шаблон регулярного выражения, аналогичный
"Title: ([^;]*?); Last Name: ([^;.]*?)"
Я хотел бы создать следующую матрицу из приведенной выше строки:
[ ][,1] [,2]
[1,] Sir John
[2,] Mr. Smith
Я успешно выполнил это в PHP на удаленном сервере, используя preg_match_all
функцию; однако текстовые файлы, к которым я обращаюсь, относительно большие (не огромные, но медленные для загрузки в любом случае). Создание этого в R сэкономит значительное количество времени.
Я прочитал об использовании grep
и т. Д. В R, Но каждый найденный мной пример ищет шаблоны в векторе, и я не смог сгенерировать матрицу, как описано выше.
Я также играл с stringr
пакетом, но опять же мне не удалось создать матрицу.
Мне это кажется обычной задачей, поэтому я уверен, что кто-то умнее меня уже нашел решение раньше.
Комментарии:
1. это довольно четко определенный вопрос; вы можете начать с
stringr::str_extract_all
(с регулярного"Title: ([^;]*) and Last Name: ([^;.]*)"
strsplit
выражения), но указанное вами регулярное выражение (я думаю) не совсем соответствует «Титул: мистер; Фамилия: Смит» …2. В начале ваш шаблон false.
(?i)Title: ([^;]*)(?:;| and) Last Name: ([^;.]*)
кажется, соответствует вашим требованиям.3. Вы правы, я изменил пример строки, но забыл обновить регулярное выражение. Сейчас я это исправил.
Ответ №1:
Рассмотрим следующий вариант, используя regmatches
:
x <- 'This is a sample string written like a paragraph. In this string two sets of information exist. Each set contains two variables. We want to extract the sets and variables within those sets. Each information set is formatted the same way. The first set is Title: Sir; Last Name: John; and the second set is Title: Mr.; Last Name: Smith.'
m <- regmatches(x, gregexpr('(?i)Title: \K[^;] |Last Name: \K[^;.] ', x, perl=T))
matrix(unlist(m), ncol=2, byrow=T)
Вывод:
[,1] [,2]
[1,] "Sir" "John"
[2,] "Mr." "Smith"
Комментарии:
1. 1 (из более ранних), пришлось искать \K, действительно интересно. Вернулся, чтобы прокомментировать, что вам, вероятно, не нужны скобки для записи, но, похоже, вы это уже учли!
2. @BrodieG Да, я забыл их убрать.
Ответ №2:
По какой-то причине, похоже, не существует простого способа извлечения захваченных совпадений в базе (я бы хотел regmatches
также работать с захваченными группами, но это не так). В итоге я написал свой собственный, вы можете найти его в regcapturedmatches.R. он будет работать с
a <- «Первый набор — это титул: сэр и фамилия: Джон; а второй набор — это титул: мистер и фамилия: Смит».
m<-gregexpr("Title: ([^;]*) and Last Name: ([^;.]*)", a, perl=T, ignore.case=T)
regcapturedmatches(a,m)[[1]]
Это вернет
[,1] [,2]
[1,] "Sir" "John"
[2,] "Mr." "Smith"
(Я добавил [[1]], потому что вы сказали, что будете работать только с одной строкой за раз. Функция может работать с вектором и возвращает результаты в виде списка. На самом деле, в R каждая вещь является вектором, поэтому нет такой вещи, как «одиночная» строка, у вас просто есть вектор строк длиной 1.)
Конечно, этот метод так же хорош, как и ваше регулярное выражение. Мне пришлось немного изменить ваши примерные данные, чтобы ваше выражение соответствовало более чем одному названию / имени.
Комментарии:
1. Есть способ получить захваченные совпадения (
regexec
regmatches
), но только для первого совпадения.str_match_all
instringr
неоднократно использует вышеуказанное, чтобы повторить то, чтоgregexec
было бы, если бы оно существовало.
Ответ №3:
Вот stringr
версия:
library(stringr)
str_match_all(x, pattern)
Выдает:
[[1]]
[,1] [,2] [,3]
[1,] "Title: Sir and Last Name: John" "Sir" "John"
[2,] "Title: Mr. and Last Name: Smith" "Mr." "Smith"
Обратите внимание, что мне пришлось отредактировать ваш текст так, чтобы второй текст также имел форму «и фамилия:». Чтобы получить вашу матрицу, вы можете просто сделать:
result[[1]][[-1]] # assumes the above is in `result`
Одним из ограничений этого является то, что он использует regexec
, который не поддерживает регулярные выражения perl.