Как заменить только указанные c группы в совпадении в R с помощью пакета stringr? - PullRequest
1 голос
/ 21 апреля 2020

В моем проекте R я использую пакет stringr для выполнения операций регулярного выражения.

text <- "My code #snippet wanna get this# is simple"
pattern <- "#([^ \t]+) (.+)#"

pattern ищет вещи внутри #...#. Следующий код:

stringr::str_match_all(text, pattern)

Предоставит мне содержимое групп, на которые я нацеливаюсь:

[[1]]
     [,1]                       [,2]      [,3]            
[1,] "#snippet wanna get this#" "snippet" "wanna get this"

Как заменить содержимое группа 3 (и только это) с другим текстом? Окончательный желаемый результат будет:

My code #snippet REPLACED WITH THIS# is simple

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

1 Ответ

1 голос
/ 21 апреля 2020

Вы можете захватить то, что вам нужно сохранить, и просто сопоставить то, что вам нужно заменить, используйте

> gsub("(#[^ \t#]+ )[^#]*(#)", "\\1REPLACED WITH THIS\\2", text)
[1] "My code #snippet REPLACED WITH THIS# is simple"

Подробности

  • (#[^ \t#]+ ) - Группа 1: #, затем любые 1+ символов, кроме #, пробел и табуляция и пробел
  • [^#]* - 0+ символов, кроме #
  • (#) - группа 2: a # char

Другой способ: используйте gsubfn с шаблоном, в котором все части шаблона объединены в отдельные группы, а затем восстановите замену после выполнения необходимых манипуляций. :

> gsubfn::gsubfn("(#[^ \t#]+ )([^#]*)(#)", function(x, y, z) paste0(x, "REPLACED WITH THIS", z), text)
[1] "My code #snippet REPLACED WITH THIS# is simple"

Здесь x, y и z относятся к группам, определенным в шаблоне:

(#[^ \t#]+ )([^#]*)(#)
| --- x ---||- y -||z|

С stringr вы можете - но вы должны быть очень осторожны с этим - используйте шаблон с lookbehind / lookahead:

> stringr::str_replace_all(text, "(?<=#[^ \t#]{1,1000} )[^#]*(?=#)", "REPLACED WITH THIS")
[1] "My code #snippet REPLACED WITH THIS# is simple"

Lookbehind (?<=#[^ \t#]{1,1000} ) работает, потому что он соответствует известной длине шаблон ({1,1000} говорит, что может быть от 1 до 1000 вхождений любых символов, кроме пробела, табуляции и #), и это " ограниченная ширина lo поддерживается okbehind", поскольку stringr использует библиотеку регулярных выражений ICU .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...