Найти шаблоны в строке, содержащей подстановочный знак и экранирование - PullRequest
0 голосов
/ 28 февраля 2019

Я часами искал в Интернете и пробовал несколько альтернатив, но не смог найти удовлетворительного решения.У меня есть строка с именем tmp_txt , содержащая несколько статей, которые начинаются с

"Newspaper.com \tTopic \tXX.XX.2015\r\n\t\r\n\r\nher_goes_the_title\r\n\r\ntext_containing_\r\n\r\nsometimes"

, причем XX.XX.2015 - это дата изменения (но всегда в 2015 году).

Я хочу найти все даты (XX.XX.2015) и все заголовки (here_goes_the_title) для записи их в кадр данных (соответствующие даты и заголовки в одну строку, но в разные столбцы).

До сих пор,мое лучшее решение находит все даты, но также немного их окружения, например:

dates <- str_match_all(tmp_text, "\t(.*?).2015")

приводит к

"\tTopic \t15.09.2015"

и т. д.

Поиск названий оченьсложнее, потому что их можно найти только после первой \r\n\t\r\n\r\n -последовательности в каждой статье и до \r\n\r\n -последовательности, которая встречается в статье несколько раз.

Есть ли у вас какие-либо решения?

Заранее спасибо, Ханно

1-е редактирование

Хорошо, как предложено r2evans, вот несколько примеров:

Süddeutsche.de \tPolitik \t15.09.2013\r\n\t\r\n\r\nSyrien-Konflikt\r\n\r\nHollande dämpft Erwartungen an Chemiewaffen-Plan\r\n\r\n

дата должна быть

15.09.2013

заголовок должен быть

Syrien-Konflikt

было бы неплохо, если быбыть также решением для получения второго заголовка:

Hollande dämpft Erwartungen an Chemiewaffen-Plan

Однако, есть несколько случаев, когда заголовку предшествует нерелевантная информация:

\r\nSüddeutsche.de \tComputer \t07.09.2013\r\n\t\r\n\r\nhttp://www.sueddeutsche.de/digital/syrische-elektronische-armee-wie-syrische-hacker-im-netz-fuer-assad-kaempfen-1.1764980\r\n\r\nSyrische Elektronische Armee\r\n\r\nWie syrische Hacker im Netz für Assad kämpfen\r\n\r\n

дата должна быть:

07.09.2013

заголовок должен быть:

Syrische Elektronische Armee

второй заголовок должен быть

Wie syrische Hacker im Netz für Assad kämpfen

Однако иногда неправильная информация состоит из двух строк, как здесь:

Süddeutsche.de \tPolitik \t03.09.2013\r\n\t\r\nKurz\r\n\r\nhttp://www.sueddeutsche.de/politik/syrisch-tuerkische-grenze-mindestens-sechs-menschen-sterben-bei-explosion-1.1761804\r\n\r\nSyrisch-türkische Grenze\r\n\r\nMindestens sechs Menschen sterben bei Explosion\r\n\r\nBei einer Explosion von Munition sind an der syrisch-türkischen Grenze...

дата:

03.09.2013

title:

Syrisch-türkische Grenze

second title:

Mindestens sechs Menschen sterben bei Explosion

Первое решение, предложенное r2evans, работает хорошо.Тем не менее, я знаю, что есть X статей, и к настоящему времени функция возвращает X дат (что правильно), но только X-2 заголовков!

Я понимаюНе знаю, какие названия не найдены должным образом.Поэтому я хотел бы использовать функцию, которая показывает мне первые 50 символов после даты, что поможет мне найти проблемные случаи при ручном поиске, например,

Süddeutsche.de \tPolitik \t03.09.2013\r\n\t\r\nKurz\r\n\r\nhttp://www.sueddeutsche.de/politik/syrisch-tuerkische-grenze-mindestens-sechs-menschen-sterben-bei-explosion-1.1761804\r\n\r\nSyrisch-türkische Grenze\r\n\r\nMindestens sechs Menschen sterben bei Explosion\r\n\r\nBei einer Explosion von Munition sind an der syrisch-türkischen Grenze...

возврат должен быть:

03.09.2013\r\n\t\r\nKurz\r\n\r\nhttp://www.sueddeutsche.de/p

Если бы у вас было лучшее решение, я был бы рад узнать.

Если остались вопросы, не стесняйтесь спрашивать.Дайте мне также знать, если вам нужно загрузить txt.file.

Cheers, Hanno

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Базовый раствор R.Использование Jonny's txt,

txt <- "Newspaper.com \tTopic \t12.02.2015\r\n\t\r\n\r\nher_goes_the_title\r\n\r\ntext_containing_\r\n\r\nsometimes"

regmatches(txt, gregexpr("\\b[0-9]{2}\\.[0-9]{2}\\.[0-9]{4}\\b", txt))
# [[1]]
# [1] "12.02.2015"
regmatches(txt, gregexpr("(?<=\r\n\t\r\n\r\n)[^\r\n]+(?=\r\n\r\n)", txt, perl = TRUE))
# [[1]]
# [1] "her_goes_the_title"

Использование gregexpr хорошо для нескольких совпадений.Тем не менее, он может найти более одной даты в строке, поэтому будьте осторожны, если вы начнете видеть этот шаблон.(Есть простые способы исправить это, если вы думаете, что у вас это будет, например lapply(x, `[[`, 1), где x - возвращение сверху.) Вы можете обмануть и использовать только regexpr, если вы работаете только с однимстрока, но векторизация, вероятно, хорошая вещь в долгосрочной перспективе.

Объяснение:

"\\b[0-9]{2}\\.[0-9]{2}\\.[0-9]{4}\\b"
 ^^^                              ^^^  word boundaries before/after
    ^^^^^      ^^^^^      ^^^^^        character range, just digits here
         ^^^        ^^^        ^^^     number of characters in preceding match
            ^^^        ^^^             the literal dot "."

и

"(?<=\r\n\t\r\n\r\n)[^\r\n]+(?=\r\n\r\n)"
 ^^^^^^^^^^^^^^^^^^^                       must have this pattern before,
                                              but does not consume it
                            ^^^^^^^^^^^^   must have the pattern after, no consume
                    ^^^^^^^                any character not one of \r \n
                           ^               one or more of preceding match

Использование (?<= и (?= требуется perl=TRUE.

0 голосов
/ 28 февраля 2019

Зависит от того, насколько жесткой является структура до даты и заголовка.Вы упоминаете, что заголовок отличается от названия, поэтому было бы здорово, если бы вы могли предоставить нам еще несколько строк в векторе с требуемыми выходными заголовками.

Если это не противоречит, вы можете использовать несоответствующие группы, чтобы удалить части, которые вам не интересны, например,

txt <- "Newspaper.com \tTopic \t12.02.2015\r\n\t\r\n\r\nher_goes_the_title\r\n\r\ntext_containing_\r\n\r\nsometimes"

library(stringi)

before_date <- "Newspaper.com \tTopic \t"
# non-matching bit before. Getting number in format nn-nn-nnnn
date <- stringi::stri_extract_first_regex(txt, 
                                          sprintf("(?<=%s)\\d{2}.\\d{2}.\\d{4}",
                                                  before_date))
date

before_title <- sprintf("%s%s\r\n\t\r\n\r\n", before_date, date)
# find all characters not \r or \n and return, after the initial sequence
title <- stringi::stri_extract_first_regex(txt,
                                           sprintf("(?<=%s)[^\\r\\n]*",
                                                   before_title))
title

Здесь (?<=News)paper вернется просто paper при извлечении этогошаблон регулярного выражения, например регулярное выражение с группой без захвата с использованием stringr в R

...