5

I have a string that looks like the following:

x <- "01(01)121210(01)0001"

I want to split this into a vector so that i get the following:

[1] "0" "1" "(01)" "1" "2" "1" "2" "1" "0" "(01)" "0" "0" "0" "1"

The (|) could be [|] or {|} and the number of digits between the brackets can be 2 or more.

I've been trying to do this by separating on the brackets first:

unlist(strsplit(x, "(?<=[\\]\\)\\}])", perl=T))
[1] "01(01)" "121210(01)" "0001"

or unlist(strsplit(x, "(?<=[\\[\\(\\{])", perl=T))
[1] "01(" "01)121210(" "01)0001"

but I can't find a way to combine the two together. Then, I was hoping to split the elements not containing the brackets.

I'd be really grateful if someone can help me out with this or know of a more elegant way to do this.

Many thanks!

David Arenburg
  • 91,361
  • 17
  • 137
  • 196

4 Answers4

4

Just change the PERL option to TRUE and split the input string based on the below pattern.

(?<!\(|^)(?!\)|\d\)|$)

DEMO

R regex would be,

"(?<!\\(|^)(?!\\)|\\d\\)|$)"
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
3

This is another way:

unlist(strsplit(x, '\\([^)]*\\)(*SKIP)(*F)|(?=)', perl=T))
# [1] "0"    "1"    "(01)" "1"    "2"    "1"    "2"    "1"    "0"    "(01)" "0"    "0"    "0"    "1" 

\\([^)]*\\) matches anything in parentheses, and (*SKIP)(*F) tells the regular expression engine to fail on this pattern and if it finds that pattern in the string, do not re-test that part of the string using the alternative pattern on the other side of the |. The pattern on the other side of the | is (?=), and this matches the space between characters.

Matthew Plourde
  • 43,932
  • 7
  • 96
  • 113
  • I really liked this answer too, but it seems I can only select one. Really sorry about this. BTW, how would I modify this to use { } or [ ] ? – mamboSC4649 Aug 07 '14 at 08:09
1

This can be done without zero width look ahead/behind expressions using strapply in the gsubfn package. The regular expression matches a digit or a ( until the next ).

library(gsubfn)

strapply(x, "\\d|\\(.*?\\)", c, perl = TRUE)[[1]]

giving:

 [1] "0"    "1"    "(01)" "1"    "2"    "1"    "2"    "1"    "0"    "(01)"
[11] "0"    "0"    "0"    "1"  

Note: In the example shown in the question the part inside (...) is always two digits. If that is always the case it can be simplified further to:

strapplyc(x, "\\d|\\(...")[[1]]

UPDATE Added note.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
1

An other possible way:

unlist(strsplit(x, '(?!\\(?\\d*\\))', perl=T))

Shorter but, less efficient than Matthew Plourde way

or a way like G. Grothendieck wrotes:

m<-gregexpr("\\d|\\([^)]*\\)", x)
regmatches(x, m)
Casimir et Hippolyte
  • 88,009
  • 5
  • 94
  • 125