2015-05-15 2 views
4

Предположим, что вы хотите заменить AXA на AAA, но также и AXXXXXA с AAAAAAA.Заменить группу захвата повторением одного символа при сохранении длины группы захвата

В принципе любое количество символов X между двумя A s с соответствующим числом A s.

Использование gsub() Я пробовал:

gsub(x = "AXA", pattern = "(A)(X+)(\\1)", replacement = "\\1\\1\\1") 

который дает AAA. Тем не менее, это AAA независимо от того, как долго X+ получает. Как я могу получить доступ к длине подгруппы 2 на выходе?

Возможный дубликат этого: Replace repeating character with another repeated character

Но ИМХО достаточно различен для отдельного вопроса.

+1

это 'x' символ означает любой символ или конкретно' x'? –

+0

X - пример символа, который нужно заменить. Может быть любым персонажем, но он не меняется в файле. –

+0

Итак, 'X' всегда один и тот же символ внутри файла? – zx8754

ответ

4

У вас есть фиксированный шаблон замены: вы снимаете A в первой группе, поэтому \\1 относится к A. Таким образом, вы получаете 3 As. Вам нужен другой подход: замените все последовательные X до A и после A. Можно с Perl-стиль регулярных выражений:

input = "AXXXA" 
gsub("(?:A|(?<!^)\\G)\\KX(?=X*A)", "A", input, perl=TRUE) 

Вывод demo code:

[1] "AAAAA" 

\G заставляет матч подряд, и \K помогает нам отрезать первоначально согласованный A. Оператор (?=X*A) уверен, что у нас есть число X до A.

EDIT:

Этот подход работает с длинными строками, тоже (here, мы заменяем каждую Xyz между 123 с A):

input = "123XyzXyzXyz123" 
gsub("(?:123|(?<!^)\\G)\\KXyz(?=(?:Xyz)*123)", "A", input, perl=TRUE) 

Выход: [1] "123AAA123"

EDIT 2:

Чтобы заменить любые буквы между 2 A s мы можем использовать \p{L} сокращенную класс символов, чтобы соответствовать любой букве, прежде чем A:

gsub("(?:A|(?<!^)\\G)\\K\\p{L}(?=\\p{L}*A)", "A", input, perl=TRUE) 
=> [1] "XSDFAAAAAA" 
+1

Это не работает для 'AsdfsA' и' XSDFADDDDA'. – zx8754

+0

@ zx8754: Как точно это не срабатывало? Не могли бы вы объяснить тесты? Я не вижу никакой проблемы [здесь] (https://ideone.com/Ylx8oV): 'gsub (" (?: A | (? '[1]" XSDFAAAAAA "' Шаблон вместо 'X' может быть любым, подход работает. –

+0

ОК, работает версия «EDIT 2». Я уже поддержал, просто хотел попросить сделать решение более надежным, спасибо. – zx8754

Смежные вопросы