Негативный просмотр переменной длины для замены разделителей списка и конца строки - PullRequest
1 голос
/ 27 февраля 2020

I sh для вставки индекса после значений, которые пропускают индекс в строке значений с разделителями, включая последнее.

s <- "Dee, DP(Dee, D. P.)[1];Uppala, SM(Uppala, S. M.);Simmons, AJ(Simmons, A. J.);Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)"
gsub("(?<!\\[\\d\\])(;|$)", "\\[0\\]\\2", s, perl=TRUE)

Этот код дает мне пропущенные разделители:

"Dee, DP(Dee, D. P.)[1];Uppala, SM(Uppala, S. M.)[0]Simmons, AJ(Simmons, A. J.)[0]Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)[0]"

Код аналогичным образом обрабатывает случай, когда последнее значение уже имеет индекс:

s <- "Dee, DP(Dee, D. P.)[1];Uppala, SM(Uppala, S. M.);Simmons, AJ(Simmons, A. J.);Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)[3]"

Давать, на этот раз (разделители по-прежнему отсутствуют):

"Dee, DP(Dee, D. P.)[1];Uppala, SM(Uppala, S. M.)[0]Simmons, AJ(Simmons, A. J.)[0]Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)[3]"

Мне нужно назад пропущенные разделители, например, в первом случае:

"Dee, DP(Dee, D. P.)[1];Uppala, SM(Uppala, S. M.)[0];Simmons, AJ(Simmons, A. J.)[0];Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)[0]"

Кроме того, я хотел бы, чтобы код также обрабатывал индексы более чем одного di git, то есть 10, 100, et c. (переменная длина), например:

s <- "Dee, DP(Dee, D. P.)[10];Uppala, SM(Uppala, S. M.);Simmons, AJ(Simmons, A. J.);Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)"

или

s <- "Dee, DP(Dee, D. P.)[10];Uppala, SM(Uppala, S. M.);Simmons, AJ(Simmons, A. J.);Kobayashi, S(Kobayashi, S.)[2];Andrae, U(Andrae, U.)[3]"

1 Ответ

1 голос
/ 27 февраля 2020

В вашем шаблоне замены \2 относится к несуществующей группе № 2. (?<!...) является негативным взглядом сзади и в отличие от групп захвата не заставляет механизм регулярных выражений выделять какой-либо специальный буфер памяти для его совпадающего значения.

Вы должны использовать \1, а не \2.

Чтобы решить шаблон переменной ширины в заднем плане, вы можете использовать двухэтапный подход с использованием шаблона PCRE с глаголами SKIP-FAIL:

s <- gsub("\\[\\d+];(*SKIP)(*F)|(;)", "[0]\\1", s, perl=TRUE)
sub("(?s)^(?!.*\\[\\d+]$)(.*)", "\\1[0]", s, perl=TRUE)

См. Демонстрационный пример regex # 1 / regex demo # 2 и R demo online

Pattern # 1 details

  • \[\d+];(*SKIP)(*F) - [, 1+ цифр, ] и затем ;; (*SKIP)(*F) удаляет этот сопоставленный текст из общего буфера памяти совпадений и продолжает поиск шаблона регулярного выражения в том месте, где произошел сбой
  • | - или
  • (;) - Group 1 (\1 в шаблоне замены): ; символ.

Шаблон # 2

  • (?s) - поворачивает режим точек, чтобы . мог соответствовать любому символу, как в регулярном выражении TRE (используется sub без perl=TRUE)
  • ^ - начало строки
  • (?!.*\[\d+]$) - a отрицательный взгляд на то, что в конце строки [, 1+ цифр и ] нет
  • (.*) - вся строка записана в группе 1.

Или, если вы можете использовать stringr и знаете, что число цифр меньше некоторого значения, скажем, 100, вы можете использовать это lookbehind ограниченной ширины Функция библиотеки ICU:

stringr::str_replace_all(s, "(?<!\\[\\d{1,100}])(;|$)", "[0]\\1")

Здесь (?<!\[\d{1,100}]) соответствует местоположению в строке, которому непосредственно не предшествуют [, от 1 до 100 цифр, а затем ].

...