R регулярное выражение с длинным выражением - PullRequest
0 голосов
/ 28 октября 2019

У меня длинный символ, извлеченный из PDF-файла. Ниже MWE:

MWE <- "4 BLABLA\r\n Table 1. Real GDP\r\n Percentage changes\r\n 2016 2017 \r\nArgentina -2.5 2.7\r\nAustralia 2.6 2.5\r\n BLABLA \r\n Table 2. Nominal GDP\r\n Percentage changes\r\n 2011 2012\r\nArgentina 31.1 21.1\r\nAustralia 7.7 3.3\r\n"

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

MWE_1 <- as.list(strsplit(MWE, "(?<=[Table\\s+\\d+\\.\\s+(([A-z]|[ \t]))+\\r\\n])"))

> MWE_1
[[1]]
[1] "4 BLABLA\r\n "                                                                                 
[2] " Percentage changes\r\n 2016 2017 \r\nArgentina -2.5 2.7\r\nAustralia 2.6 2.5\r\n BLABLA 5\r\n "
[3] " Percentage changes\r\n 2011 2012\r\nArgentina 31.1 21.1\r\nAustralia 7.7 3.3\r\n"         

Но я бы хотел оставить разделитель, который является здесь действительно длинным регулярным выражением. Я посмотрел немного, и, кажется, хороший способ - попробовать lookbehinds . Тем не менее, я не знаю, как связать мое длинное регулярное выражение. Например,
MWE_2 <- as.list(strsplit(MWE, "(?<=[Table\\s+\\d+\\.\\s+(([A-z]|[ \t]))+\\r\\n])"))

выдает ошибку:

invalid regular expression '(?<=[Table\s+\d+\.\s+(([A-z]|[  ]))+\r\n])', reason 'Invalid regexp'

Как сделать это компактным способом?

Кроме того, существует ли прямой способ не сохранять первый элемент?

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Попробуйте заглянуть вперед и упростите то, что вы ищете:

При условии экранирования конкретной строки.

(?=Table \\d+\\.)

Обязательно включите perl=TRUE

https://regex101.com/r/Cpyu6k/1

0 голосов
/ 06 ноября 2019

Мне не ясно, почему он не работает с ?<=

Регулярные выражения, используемые в R , говорят (у вас есть повторениеквантификаторы + в шаблоне):

Шаблоны (?<=...) и (?<!...) являются эквивалентами в виде заглядывания: они не допускают квантификаторы повторения и не \C в ....


У меня все еще есть проблема с 5 элементами, а не начало подсказки, почему,

> MWE_2
[[1]]
[1] "4 BLABLA\r\n"
[2] " "
[3] "Table 1. Real GDP\r\n Percentage changes\r\n 2016 2017\r\nArgentina -2.5 2.7\r\nAustralia 2.6 2.5\r\n BLABLA \r\n"
[4] " "
[5] "Table 2. Nominal GDP\r\n Percentage changes\r\n 2011 2012\r\nArgentina 31.1 21.1\r\nAustralia 7.7 3.3\r\n"

, но я могу впоследствии удалить пустые элементы…

В индексах [2] и [4] нет пустых элементов - эти элементы содержат один пробел. Это связано с тем, что шаблон в strsplit(MWE, "(?= Table \\d+\\.)", perl=TRUE) соответствует разделителю нулевой длины, поскольку он содержит только положительное утверждение нулевой ширины и не содержит фактического символьного элемента-разделителя;strsplit пошел бы в бесконечный цикл, если бы он строго следовал своему документированному алгоритму

repeat {
        if the string is empty
            break.
        if there is a match
            add the string to the left of the match to the output.
            remove the match and all to the left of it.
        else
            add the string to the output.
            break.
    }
- но в его коде есть специальная обработка:
            /* Match was empty. */
            pt[0] = *bufp;
            pt[1] = '\0';
            bufp++;

Это приводит к тому, что один символ находится в позиции пустое совпадение , которое должно быть возвращено (пробел в вашем случае), и поиск, который следует продолжить после него.

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

strsplit(MWE, " (?=Table \\d+\\.)", perl=TRUE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...