Использование strsplit() в R, игнорирование чего-либо в скобках

Я пытаюсь использовать strsplit() в R, чтобы разбивать строку на куски на основе запятых, но я не хочу разделить что-либо в круглых скобках. Я думаю, что ответ - это регулярное выражение, но я пытаюсь получить код правильно.

Итак, например:

x <- "This is it, isn't it (well, yes)"
> strsplit(x, ", ")
[[1]]
[1] "This is it"     "isn't it (well" "yes)" 

Когда я хочу:

[1] "This is it"     "isn't it (well, yes)"

Ответ 1

Мы можем использовать PCRE regex to FAIL any ,, что следует, что a ( до ) и разбивается на ,, за которым следует 0 или более пробелов (\\s*)

 strsplit(x, '\\([^)]+,(*SKIP)(*FAIL)|,\\s*', perl=TRUE)[[1]]
 #[1] "This is it"           "isn't it (well, yes)"

Ответ 2

Я хотел бы предложить другое регулярное выражение с (*SKIP)(*F), чтобы игнорировать все подстроки (...) и только соответствовать запятым вне подстроек в скобках:

x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too)"
strsplit(x, "\\([^()]*\\)(*SKIP)(*F)|\\h*,\\h*", perl=T)

Смотрите демоверсия IDEONE

Подробнее о о том, как (* SKIP) или (* F) работать с regex? здесь. Регулярное выражение соответствует:

  • \( - открывающая скобка
  • [^()]* - ноль или более символов, кроме ( и )
  • \) - закрывающая скобка
  • (*SKIP)(*F) - глаголы, которые продвигают текущий индекс регулярных выражений к позиции после закрытия скобки
  • | - или...
  • \\h*,\\h* - запятая, окруженная нулевыми или более горизонтальными пробелами.

Ответ 3

Другой подход:

Добавление в строку образца @Wiktor,

x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too). Let look, does it work?"

Теперь волшебство:

> strsplit(x, ", |(?>\\(.*?\\).*?\\K(, |$))", perl = TRUE)
[[1]]
[1] "This is it"                                       
[2] "isn't it (well, yes)"                             
[3] "and (well, this, that, and this, too). Let look"
[4] "does it work?"  

Итак, как , |(?>\\(.*?\\).*?\\K(, |$)) соответствует?

  • | захватывает обе группы с обеих сторон, обе
    • слева, строка ,
    • и справа, (?>\\(.*?\\).*?\\K(, |$)):
      • (?> ... ) устанавливает атомную группу, которая не позволяет возвратить назад, чтобы переоценить, что она соответствует.
      • В этом случае он ищет открытую скобку (\\(),
      • то любой символ (.) повторяется от 0 до бесконечности (*), но как можно меньше (?), т.е. . оценивается лениво.
      • Предыдущее повторение . затем ограничивается первой закрывающей скобкой (\\)),
      • за которым следует еще один набор символов, повторяемый 0 как можно меньше (.*?)
      • с a \\K в конце, который удаляет совпадение до сих пор и устанавливает начальную точку нового совпадения.
      • Предыдущий .*? ограничен группой захвата (( ... )) с |, которая либо
        • выбирает фактическую текстовую строку, ,,
        • или переместит \\K в конец строки $, если запятых больше нет.

* Уф. *

Если мое объяснение сбивает с толку, см. документацию, связанную выше, и проверьте regex101.com, где вы можете поместить в вышеупомянутое регулярное выражение ( single escaped- \ вместо двойного escape-стиля R-\\) и тестовой строки, чтобы увидеть, что она соответствует, и получить объяснение того, что она делает. Вам нужно будет установить модификатор g (global) в поле рядом с полем regex, чтобы отображать все совпадения, а не только первые.

Счастливый strsplit ing!