Отрицательный просмотр назад в R с разделением на несколько слов

Я использую R для обработки строк и хочу идентифицировать строки с определенным корнем слова, которым не предшествует другое слово с определенным корнем слова.

Вот простой игрушечный пример. Скажем, я хотел бы идентифицировать строки, в которых слово «cat / s» не предшествует «dog / s» где-либо в строке.

 tests = c(
   "dog cat",
   "dogs and cats",
   "dog and cat", 
   "dog and fluffy cats",
   "cats and dogs", 
   "cat and dog",  
   "fluffy cats and fluffy dogs")  

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

 pattern = "(dog(s|).*)(cat(s|))"
 grep(pattern, tests, perl = TRUE, value = TRUE)

[1] "dog cat"  "dogs and cats"   "dog and cat"   "dog and fluffy cats"

У моего отрицательного взгляда назад есть проблемы:

 neg_pattern = "(?<!dog(s|).*)(cat(s|))"
 grep(neg_pattern, tests, perl = TRUE, value = TRUE)

Ошибка в grep (neg_pattern, tests, perl = TRUE, value = TRUE): недопустимое регулярное выражение

Вдобавок: Предупреждающее сообщение: В grep (neg_pattern, tests, perl = TRUE, value = TRUE): ошибка компиляции шаблона PCRE 'утверждение просмотра назад не имеет фиксированной длины' at ') (cat (s |))'

Я понимаю, что. * Не имеет фиксированной длины, поэтому как я могу отклонить строки, в которых слово «собака» перед словом «кошка» разделено любым количеством других слов?


person Nancy    schedule 30.06.2017    source источник
comment
Да, у вашего отрицательного просмотра вперед есть проблемы, потому что это не просмотр вперед, это просмотр назад, который не может иметь шаблон неизвестной длины. Похоже, вы можете просто использовать lookahead таким образом - "^(?!.*dog.*cat).*cat"   -  person Wiktor Stribiżew    schedule 01.07.2017
comment
См. ideone.com/v6mpjt.   -  person Wiktor Stribiżew    schedule 01.07.2017
comment
Похоже, вы не можете делать то, что хотите, в одном регулярном выражении в R. Там также есть тот же вопрос с хорошим ответом здесь: stackoverflow.com/questions/3796436 /   -  person thc    schedule 01.07.2017
comment
@ WiktorStribiżew Я пытаюсь понять компонент корня слова в моем вопросе. Например, кошки против кошки против гусеницы ... Могу ли я использовать cat (s | erpillar |) и т. Д.   -  person Nancy    schedule 01.07.2017
comment
@ WiktorStribiżew Этот пример работает, но я также пытаюсь получить более общее представление о синтаксисе. Я вообще-то не забочусь о кошках и собаках, в конце концов, моя проблема интереснее: P   -  person Nancy    schedule 01.07.2017
comment
Тогда никогда не упрощайте слишком много. Опубликуйте детали реального сценария проблемы. Тот, кто не спит, непременно поможет вам.   -  person Wiktor Stribiżew    schedule 01.07.2017
comment
@thc Спасибо за ссылку. Отсутствие легко читаемых примеров - главная причина, по которой я разместил этот вопрос.   -  person Nancy    schedule 01.07.2017
comment
@ WiktorStribiżew Моего примера достаточно, чтобы рассмотреть параметры моего фактического вопроса - несколько окончаний слов, строки, которые не начинаются с ключевого слова и т. Д. Я считаю, что в шаблонных вопросах есть ценность, чтобы помочь будущим пользователям. Если у вас есть идеи о том, как отредактировать вопрос, чтобы расширить функциональность и при этом сохранить нейтралитет, изменения, безусловно, приветствуются. Спасибо за помощь!   -  person Nancy    schedule 01.07.2017
comment
строки, которые не начинаются с ключевого слова, не рассматриваются в вашем вопросе.   -  person Wiktor Stribiżew    schedule 01.07.2017
comment
Как отмечалось в приведенных выше комментариях, вы не можете получить желаемое из одного регулярного выражения. Однако обходной путь - найти все строки cat, а затем удалить все строки dog. * Cat. Попробуйте это: grep("dog.*cat", grep("cat", tests, perl = TRUE, value = TRUE), perl = TRUE, value = TRUE, invert=TRUE)   -  person G5W    schedule 01.07.2017


Ответы (1)


Надеюсь, это поможет:

tests = c(
  "dog cat",
  "dogs and cats",
  "dog and cat", 
  "dog and fluffy cats",
  "cats and dogs", 
  "cat and dog",  
  "fluffy cats and fluffy dogs"
)

# remove strings that have cats after dogs
tests = tests[-grep(pattern = "dog(?:s|).*cat(?:s|)", x = tests)]

# select only strings that contain cats
tests = tests[grep(pattern = "cat(?:s|)", x = tests)]

tests

[1] "cats and dogs"               "cat and dog"                
[3] "fluffy cats and fluffy dogs"

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

person Joshua Daly    schedule 25.09.2017