Регулярное выражение с stringr:: как найти первый экземпляр шаблона

За этим вопросом стоит попытка извлечь все ссылки, созданные knitr и latex. Не найдя другого пути, я решил прочитать в R скрипт .Rnw и использовать регулярное выражение для поиска ссылок, где синтаксис латекса \ref{caption referenced to}. В моем сценарии более 250 ссылок, и некоторые из них очень близки друг к другу.

Пример text.1 ниже работает, но не текстовый пример. Я думаю, это связано с тем, что R пыхтит до последней закрывающей скобки. Как мне остановиться на первой закрывающей скобке и извлечь то, что предшествовало ей, в открывающую скобку?

library(stringr)
text.1 <- c(" \\ref{test}", "abc", "\\ref{test2}", " \\section{test3}", "{test3")
# In the regular expression below, look back and if find "ref{", grab everything until look behind for } at end
# braces are special characters and require escaping with double backslacs for R to recognize them as braces
# unlist converts the list returned by str_extract to a vector

unlist(str_extract_all(string = text.1, pattern = "(?<=ref\\{).*(?=\\}$)"))
[1] "test"  "test2"

# a more complicated string, with more than one set of braces in an element
text <- c("text \ref{?bar labels precision} and more text  \ref{?table column alignment}", "text \ref{?table space} }")

unlist(str_extract_all(string = text, pattern = "(?<=ref\\{).*(?=\\}$)"))
character(0)

person lawyeR    schedule 27.09.2015    source источник
comment
@stribizhev, нет, не пробовал. Но я сделал это только сейчас, и они оба возвращают символ (0). Спасибо за вопрос. Причем, нет вложенных ситуаций, только одна за другой иногда.   -  person lawyeR    schedule 27.09.2015


Ответы (2)


Проблема с text заключается в том, что обратная косая черта перед «ref» интерпретируется как возврат каретки \r движком и синтаксическим анализатором R; так что вы пытаетесь сопоставить "ref", но на самом деле это (CR + "ef")...

Кроме того, * по умолчанию является жадным, что означает, что он будет совпадать настолько, насколько это возможно, и по-прежнему разрешать совпадение остальной части регулярного выражения. Используйте *? или отрицательный класс символов, чтобы предотвратить жадность.

unlist(str_extract_all(text, '(?<=\ref\\{)[^}]*'))
# [1] "?bar labels precision"   "?table column alignment" "?table space"

Как видите, вы можете использовать класс символов для соответствия (\r или r + "ef")...

x <- c(' \\ref{test}', 'abc', '\\ref{test2}', ' \\section{test3}', '{test3',
       'text \ref{?bar labels precision} and more text  \ref{?table column alignment}', 
       'text \ref{?table space} }')

unlist(str_extract_all(x, '(?<=[\rr]ef\\{)[^}]*'))

# [1] "test"                    "test2"                   "?bar labels precision"  
# [4] "?table column alignment" "?table space" 
person hwnd    schedule 27.09.2015

ОТРЕДАКТИРОВАНО

Причина, по которой он не захватил то, что находится перед закрывающей фигурной скобкой }, заключается в том, что вы добавили якорь конца строки $. Удалите $ и все заработает.

Поэтому ваш новый код должен быть таким

 unlist(str_extract_all(string = text, pattern = "(?<=ref\\{)[^}]*(?=\\})"))

См. DEMO.

person james jelo4kul    schedule 27.09.2015
comment
IMO text.1 уже поддерживался OP, проблема связана с text. - person daroczig; 27.09.2015
comment
@daroczig прав. Спасибо, Джеймс, но у меня проблемы с более сложными строками. Удаление привязки к концу строки не решает текст. - person lawyeR; 27.09.2015
comment
Отредактированный пост будет работать для сложных строк. Посмотреть демо - person james jelo4kul; 27.09.2015
comment
@дароциг. Спасибо за исправление. Ссылка и выкройка отредактированы. Теперь это должно работать - person james jelo4kul; 27.09.2015
comment
Извините, это демонстрационный код, который вы предлагаете, или отредактированный ответ. Кажется, я могу заставить работать над текстом. Что я делаю не так? - person lawyeR; 27.09.2015
comment
Попробуйте это (?<=ref\\{)[^}]*(?=\\}) - person james jelo4kul; 27.09.2015