Замена текста в gsub путем вычисления обратной ссылки

#r #regex #gsub #backreference

#r #регулярное выражение #gsub #обратная ссылка

Вопрос:

Допустим, у меня есть некоторый текст :

 myF <- "lag.variable.1 1"
 

Я хотел бы получить для всех подобных выражений следующий результат: lag.variable.2 (то есть заменить 1 1 на фактическую сумму

Следующее, похоже, не работает, похоже, что обратная ссылка не выполняется в бите eval(parse()):

 myF<-gsub("(\.\w )\.([0-9] \ [0-9] )", 
            paste0( "\1." ,eval(parse(text ="\2"))) ,
            myF )

 

Какие — нибудь советы о том , как добиться желаемого результата?
Спасибо!

Ответ №1:

Вот как вы можете использовать свой текущий шаблон с gsubfn :

 library(gsubfn)
x <- " lag.variable0.3 * lag.variable1.1 1   9892"
p <- "(\.\w )\.([0-9] \ [0-9] )"
gsubfn(p, function(n,m) paste0(n, ".", eval(parse(text = m))), x)
# => [1] " lag.variable0.3 * lag.variable1.2   9892"
 

Обратите внимание , что совпадение передается вызываемому объекту в этом случае , когда переменной присваивается группа 1 n , а группе 2 присваивается m . Возвращаемое значение представляет собой объединение содержимого группы 1 . и eval отредактированной группы 2.

Примечание. вы можете упростить вызываемую часть, используя регулярное выражение PCRE (добавить perl=TRUE аргумент) K , оператор сброса соответствия, который отбрасывает весь текст, сопоставленный до сих пор:

 p <- "\.\w \.\K(\d \ \d )"
gsubfn(p, ~ eval(parse(text = z)), x, perl=TRUE)
[1] " lag.variable0.3 * lag.variable1.2   9892"
 

Вы можете дополнительно улучшить шаблон для поддержки других операндов, заменив \ на [- /*] и, если вам нужно поддерживать числа дробными частями, замените [0-9] на \d*\.?\d :

 p <- "(\.\w )\.(\d*\.?\d [- /*]\d*\.?\d )"
## or a PCRE regex:
p <- "\.\w \.\K(\d*\.?\d [- /*]\d*\.?\d )"
 

Ответ №2:

Мы можем использовать gsubfn

 library(gsubfn)
gsubfn("(\d \ \d )", ~ eval(parse(text = x)), myF)
#[1] "lag.variable.2"

 gsubfn("\.([0-9] \ [0-9] )", ~ paste0(".", eval(parse(text = x))), myF2)
#[1] "lag.variable0.3 * lag.variable1.2   9892"
 

Или с помощью str_replace

 library(stringr)
str_replace(myF, "(\d \ \d )", function(x) eval(parse(text = x)))
#[1] "lag.variable.2"
 

Или вариант с strsplit и paste

 v1 <- strsplit(myF, "\.(?=\d)", perl = TRUE)[[1]]
paste(v1[1], eval(parse(text = v1[2])), sep=".")
#[1] "lag.variable.2"
 

данные

 myF <- "lag.variable.1 1"
myF2 <- "lag.variable0.3 * lag.variable1.1 1   9892"
 

Комментарии:

1. Спасибо! они работают, когда строка символов изолирована, как в примере. Но что, если выражение является частью более длинной строки, такой как » lag.variable. 3 * задержка.переменная.1.1 9892″

2. @satellite42 также неясно, какой из них вы хотите добавить и нужно ли вам также умножение?

3. @satellite42 каков ожидаемый результат для строки, которую вы прокомментировали

4. Мой плохой, второй пример был плохой копипастой. Для исправления у меня есть формулы, подобные второму примеру (» lag.variable0.3 * lag.variable1.1 1 9892 «), Мне нужно, чтобы это стало " lag.variable0.3 * lag.variable1.2 9892" . Спасибо за помощь 🙂

5. @satellite42 обновил сообщение с помощью gsubfn