#r #regex
#r #регулярное выражение
Вопрос:
Предположим, у меня есть следующие строки для анализа для использования в R
:
PIA 1 TC_5504_00_312010_0050 50103 AB346 type 5334
PIA 1 TC_3444_00_312010_0133 0140
PIA 1 DRW/50488665600/01/000:DW
PIA 1 TC_5635_00_312019_2644 LoremIpsum
PIA 1 TC_5635_00_312010_0040 63503 AB346 type 5334
PIA 1 TC_5635_00_312018_0223 DolorSit
PIA 1 TC_5635_00_312019_2644 DolorSit
В двух словах, логика такова:
- Захватывает все после положительного просмотра
(?<=^PIA d{1} )
- Не фиксируйте, где строка содержит либо
LoremIpsum
, либоDolorSit
Желаемый результат должен выглядеть следующим образом:
TC_5504_00_312010_0050 50103 AB346 type 5334
TC_3444_00_312010_0133 0140
DRW/50488665600/01/000:DW
TC_5635_00_312010_0040 63503 AB346 type 5334
Это то, до чего я дошел до сих пор:
(?<=^PIA d{1} )((?!.*LoremIpsum|DolorSit).)*$
Я еще намеренно не экранировался в соответствии с R
, но сделаю это позже.
Но, к сожалению, она сохраняет последнюю цифру захвата в новой группе. Мой опыт в регулярных выражениях ограничен, и я застрял, как захватить всю оставшуюся строку в группе. Я не привязан к этому подходу, и другая логика может заключаться в том, что всякий раз, когда за последней
следует буква, она должна исключать захват, но это приведет к трудностям с добавлением случаев с PIA 1 DRW/50488665600/01/000:DW
строками.
Мои образцы хранятся здесьregex101.com
Ответ №1:
Вы можете полностью избавиться от неэффективного жадного токена, заменив его простой группой чередования:
(?<=^PIA d )(?!.*(?:LoremIpsum|DolorSit)).*$
Смотрите демонстрацию регулярных выражений
Подробные сведения
(?<=
— положительный просмотр, который находится непосредственно слева от текущего местоположения, требует^
— начало строкиPIA
—PIA
d
— одна цифра
)
— конец просмотра(?!.*(?:LoremIpsum|DolorSit))
— отрицательный предварительный просмотр, который не соответствует, если есть как можно больше нулевых или более символов, отличных от символов разрыва строки, а затем следуют подстрокиLoremIpsum
илиDolorSit
сразу справа от текущего местоположения.*$
— остальная часть строки.
Смотрите R demo:
library(stringr)
x <- c("PIA 1 TC_5504_00_312010_0050 50103 AB346 type 5334",
"PIA 1 TC_3444_00_312010_0133 0140",
"PIA 1 DRW/50488665600/01/000:DW",
"PIA 1 TC_5635_00_312019_2644 LoremIpsum",
"PIA 1 TC_5635_00_312010_0040 63503 AB346 type 5334",
"PIA 1 TC_5635_00_312018_0223 DolorSit",
"PIA 1 TC_5635_00_312019_2644 DolorSit")
str_extract(x, "(?<=^PIA\ \d\ )(?!.*(?:LoremIpsum|DolorSit)).*$")
Вывод:
[1] "TC_5504_00_312010_0050 50103 AB346 type 5334"
[2] "TC_3444_00_312010_0133 0140"
[3] "DRW/50488665600/01/000:DW"
[4] NA
[5] "TC_5635_00_312010_0040 63503 AB346 type 5334"
[6] NA
[7] NA
Или вы также можете просто получить соответствующие строки, используя
res <- sub("^PIA\ \d\ (?!.*(?:LoremIpsum|DolorSit))(.*)|.*", "\1", x, perl=TRUE)
res[res != ""]
Смотрите эту демонстрацию R.
Или, если вам нужно просто grep
эти строки:
grep("^PIA\ \d\ (?!.*(?:LoremIpsum|DolorSit))", x, perl=TRUE, value=TRUE)
Смотрите эту демонстрацию R. Вывод:
[1] "PIA 1 TC_5504_00_312010_0050 50103 AB346 type 5334"
[2] "PIA 1 TC_3444_00_312010_0133 0140"
[3] "PIA 1 DRW/50488665600/01/000:DW"
[4] "PIA 1 TC_5635_00_312010_0040 63503 AB346 type 5334"
Комментарии:
1. Еще раз спасибо @Wiktor. Кажется, мне нужно многое наверстать, чтобы сделать с регулярным выражением. Это решение работает отлично.
2. выражение сработало в наборе примеров, но после экранирования в соответствии с
R
как таковым(?<=^PIA\ \d\ (?!.*(?:LoremIpsum|DolorSit))).*$
и запуска скрипта я получаю сообщение об ошибке, что шаблоны поиска должны иметь ограниченную максимальную длину `(U_REGEX_LOOK_BEHIND_LIMIT). Я полагаю, это связано с вложенным обзором в lookbehind?3. @Max Какую функцию вы используете?
str_extract
?4. Спасибо @Wiktor, так что вы в основном закрыли просмотр в собственных скобках и впоследствии вызвали просмотр в своей собственной группе. Я не знал об ограничениях в
str_extract()
!grep
Пример также полезен, поскольку у меня есть несколько случаев, когда я застрял на неограниченных поисковых системах. Я могу подтвердить, что это работает так, как ожидалось в сценарии. Большое спасибо!5. @Max Просто для полноты я также добавил ideone.com/txsS6v .