Регулярное выражение R: указание выбора выходных данных из более широких совпадений строк

Один для энтузиастов регулярных выражений. У меня есть вектор строк в формате:

<TEXTFORMAT LEADING="2"><P ALIGN="LEFT"><FONT FACE="Verdana" STYLE="font-size: 10px" size="10" COLOR="#FF0000" LETTERSPACING="0" KERNING="0">Desired output string containing any symbols</FONT></P></TEXTFORMAT>

Я знаю об опасностях разбора такого рода вещей с регулярным выражением. Однако было бы полезно знать, как эффективно извлекать выходную подстроку совпадения большей строки, то есть содержимое угловых кавычек >...< тега шрифта. Лучшее, что я могу сделать, это:

require(stringr)
strng = str_extract(strng, "<FONT.*FONT>") # select font statement
strng = str_extract(strng, ">.*<")         # select inside tags
strng = str_extract(strng, "[^/</>]+")     # remove angle quote symbols

Какой была бы самая простая формула для достижения этого в R?


person geotheory    schedule 22.10.2013    source источник


Ответы (2)


Используйте str_match, а не str_extract (или, может быть, str_match_all). Заключите часть, которую вы хотите извлечь, в круглые скобки.

str_match(strng, "<FONT[^<>]*>([^<>]*)</FONT>")

Или проанализируйте документ и извлеките содержимое таким образом.

library(XML)
doc <- htmlParse(strng)
fonts <- xpathSApply(doc, "//font")
sapply(fonts, function(x) as(xmlChildren(x)$text, "character"))

Как упоминалось в agstudy, xpathSApply принимает аргумент функции, который упрощает задачу.

xpathSApply(doc, "//font", xmlValue)
person Richie Cotton    schedule 22.10.2013
comment
Ах, скобки указывают вывод. Но в этом случае проще формула str_match(strng, "<FONT.*>(.*)</FONT>")[1,2]. Я поэкспериментировал с XML-методом, но не смог заставить его работать, так что спасибо и за это. - person geotheory; 22.10.2013
comment
и ...[,2] для вектора. - person geotheory; 22.10.2013
comment
@geotheory Есть компромисс между тем, насколько конкретным вы хотите быть в матче. Более конкретные совпадения обычно выполняются быстрее и имеют меньше ложноположительных совпадений, но у вас может быть ложноотрицательный результат, если ваш текст содержит необычные символы. - person Richie Cotton; 22.10.2013
comment
Принято к сведению. Интересно, Ричи, не могли бы вы посоветовать этот связанный вопрос повторно ваш XML-метод. Я работаю с файлом KML, но структура XML оказывается сложной для анализа. - person geotheory; 22.10.2013
comment
@RichieCotton +1!вы можете сделать короче (опустить последнюю строку) чем-то вроде xpathSApply(doc, "//font",xmlChildren)$text или xpathSApply(doc, "//font",xmlValue) - person agstudy; 22.10.2013

Вы также можете сделать это с помощью gsub, но я думаю, что в вашем входном векторе слишком много перестановок, которые могут привести к поломке...

gsub( "^.*(?<=>)(.*)(?=</FONT>).*$" , "\\1" , x , perl = TRUE )
#[1] "Desired output string containing any symbols"

Объяснение

  • ^.* - соответствует любым символам с начала строки
  • (?<=>) - положительное утверждение нулевой ширины с просмотром назад, где последующее совпадение будет работать только в том случае, если ему предшествует это, то есть >
  • (.*) - затем сопоставьте любые символы (теперь это пронумерованная группа захвата)...
  • (?=</FONT>) - ...пока не совпадете с "</FONT>"
  • .*$ - затем сопоставьте любые символы с концом строки

При замене мы заменяем все совпавшие элементы на пронумерованную группу захвата \\1, и есть только одна группа захвата, состоящая из всего, что находится между > и </FONT>.

Используйте на свой страх и риск.

person Simon O'Hanlon    schedule 22.10.2013
comment
Спасибо Саймон. Да, я слышал эту строчку: у вас возникла проблема, и вы попробовали регулярное выражение. теперь у тебя две проблемы.. :) - person geotheory; 22.10.2013