Захват после положительного просмотра, за исключением строки, содержащей исключения в R

#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
  

В двух словах, логика такова:

  1. Захватывает все после положительного просмотра (?<=^PIA d{1} )
  2. Не фиксируйте, где строка содержит либо 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 — одна цифра
    • — a
  • ) — конец просмотра
  • (?!.*(?: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 .