2016-02-11 4 views
14

Я пытаюсь использовать 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)" 
+0

Вы пытаетесь использовать фигурные скобки '(...)' как область с нерастяжимым блоком и должны поместить свое намерение в расщепление regexp. Это непростая задача. – huckfinn

ответ

14

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

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

Я бы предложил другой регулярное выражение с (*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 demo

Вы можете прочитать больше о How do (*SKIP) or (*F) work on regex? здесь. Регулярное выражение соответствует:

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

Вы увлекали аккаунт * stribizhev *? o_O –

+0

@BhargavRao: Это мой аккаунт, я просто изменил имя. Вы можете делать это раз в месяц на SO :) –

+1

Это замечательно. Благодаря! –

1

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

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

x <- "This is it, isn't it (well, yes), and (well, this, that, and this, too). Let's 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's look" 
[4] "does it work?" 

Так как же , |(?>\\(.*?\\).*?\\K(, |$)) матч?

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

* Уф. *

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

Happy strsplit ing!

+0

Очень полезно. Благодаря! –