регулярное выражение для удаления вложенных скобок - PullRequest
3 голосов
/ 17 октября 2019

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

chf <- "(Mn,Ca,Zn)5(AsO4)2((AsO3)OH)24(H2O)(OH(AsO3))(OH(AsO3)OH)"

Желаемый вывод:

"(Mn,Ca,Zn)5(AsO4)2(AsO3OH)24(H2O)(OHAsO3)(OHAsO3OH)"

Я пытаюсь это сделать, но я 'Я не могу исключить, что находится во вложенных скобках.

> str_replace_all(chf,"\\((\\w+)\\)","(gone)")

[1] "(Mn,Ca,Zn)5(gone)2((gone)OH)24(gone)(OH(gone))(OH(gone)OH)"

1 Ответ

4 голосов
/ 17 октября 2019

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

library(gsubfn)
chf <- "(Mn,Ca,Zn)5(AsO4)2((AsO3)OH)24(H2O)(OH(AsO3))(OH(AsO3)OH)"
gsubfn("\\((?:[^()]++|(?R))*\\)", ~ gsub("(^\\(|\\)$)|[()]", "\\1", x, perl=TRUE), chf, perl=TRUE, backref=0)
# => [1] "(Mn,Ca,Zn)5(AsO4)2(AsO3OH)24(H2O)(OHAsO3)(OHAsO3OH)"

\((?:[^()]++|(?R))*\) регулярное выражение - это известный PCRE-шаблон для соответствия вложенным скобкам. Как только совпадение найдено, gsubfn берет строку и удаляет все не начальные и не окончательные скобки, используя gsub("(^\\(|\\)$)|[()]", "\\1", x, perl=TRUE). Здесь (^\\(|\\)$) соответствует и захватывает первый ( и последний ) в группу 1, а затем любые ( и ) сопоставляются с [()]. Заменой является содержание группы 1.

Базовое эквивалентное решение R:

chf <- "(Mn,Ca,Zn)5(AsO4)2((AsO3)OH)24(H2O)(OH(AsO3))(OH(AsO3)OH)"
gre <- gregexpr("\\((?:[^()]++|(?R))*\\)", chf, perl=TRUE)
matches <- regmatches(chf, gre)
regmatches(chf, gre) <- lapply(matches, gsub, pattern="(^\\(|\\)$)|[()]", replacement="\\1")
> chf
# => "(Mn,Ca,Zn)5(AsO4)2(AsO3OH)24(H2O)(OHAsO3)(OHAsO3OH)"
...