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

У меня есть набор данных, как показано ниже. Я хотел бы заменить все точки между двумя 1 на 1, как показано в желаемом. Результат. Могу ли я сделать это с помощью regex в базе R?

Я пробовал:

regexpr("^1\\.1$", my.data$my.string, perl = TRUE)

Вот решение в С#

Символы между двумя точными символами

Спасибо за любые предложения.

my.data <- read.table(text='
     my.string                           state
     ................1...............1.    A
     ......1..........................1    A
     .............1.....2..............    B
     ......1.................1...2.....    B
     ....1....2........................    B
     1...2.............................    C
     ..........1....................1..    C
     .1............................1...    C
     .................1...........1....    C
     ........1....2....................    C
     ......1........................1..    C
     ....1....1...2....................    D
     ......1....................1......    D
     .................1...2............    D
', header = TRUE, na.strings = 'NA', stringsAsFactors = FALSE)

desired.result <- read.table(text='
     my.string                           state
     ................11111111111111111.    A
     ......1111111111111111111111111111    A
     .............1.....2..............    B
     ......1111111111111111111...2.....    B
     ....1....2........................    B
     1...2.............................    C
     ..........1111111111111111111111..    C
     .111111111111111111111111111111...    C
     .................1111111111111....    C
     ........1....2....................    C
     ......11111111111111111111111111..    C
     ....111111...2....................    D
     ......1111111111111111111111......    D
     .................1...2............    D
', header = TRUE, na.strings = 'NA', stringsAsFactors = FALSE)

Ответ 1

Ниже приведена опция, использующая gsub с помощью функции \G и поисковых запросов.

> gsub('(?:1|\\G(?<!^))\\K\\.(?=\\.*1)', '1', my.data$my.string, perl = TRUE)
# [1] "................11111111111111111." "......1111111111111111111111111111"
# [3] ".............1.....2.............." "......1111111111111111111...2....."
# [5] "....1....2........................" "1...2............................."
# [7] "..........1111111111111111111111.." ".111111111111111111111111111111..."
# [9] ".................1111111111111...." "........1....2...................."
# [11] "......11111111111111111111111111.." "....111111...2...................."
# [13] "......1111111111111111111111......" ".................1...2............"

Функция \G - это якорь, который может совпадать в одной из двух позиций; начало позиции строки или положение в конце последнего совпадения. Поскольку кажется, что вы хотите избежать точек в начале строки, мы используем утверждение \G(?<!^), чтобы исключить начало строки.

Управляющая последовательность \K сбрасывает исходную точку сообщенного соответствия, и все ранее использованные символы больше не включаются.

Вы можете найти общую разбивку, которая объясняет регулярное выражение здесь.

Ответ 2

Используя gsubfn, первый аргумент является регулярным выражением, которое соответствует 1 и символам между 1 и фиксирует последнее. Второй аргумент - это функция, выраженная в формуле, которая использует gsub для замены каждого символа в захваченной строке 1:

library(gsubfn)
transform(my.data, my.string = gsubfn("1(.*)1", ~ gsub(".", 1, x), my.string))

Если в строке может быть несколько пар из 1, используйте вместо этого "1(.*?)1" в качестве обычного выражения.

Визуализация. Регулярное выражение здесь достаточно просто, чтобы его можно было понять напрямую, но вот визуализация debuggex anwyays:

1(.*)1

Regular expression visualization

Демоверсия Debuggex

Ответ 3

Вот опция, которая использует относительно простое регулярное выражение и стандартную комбинацию gregexpr(), regmatches() и regmatches<-() для идентификации, извлечения, работы и замены подстрок, соответствующих этому регулярному выражению.

## Copy the character vector
x <- my.data$my.string
## Find sequences of "."s bracketed on either end by a "1"
m <- gregexpr("(?<=1)\\.+(?=1)", x, perl=TRUE)
## Standard template for operating on and replacing matched substrings
regmatches(x,m) <- sapply(regmatches(x,m), function(X) gsub(".", "1", X))

## Check that it worked
head(x)
# [1] "................11111111111111111." "......1111111111111111111111111111"
# [3] ".............1.....2.............." "......1111111111111111111...2....."
# [5] "....1....2........................" "1...2............................."