match and extract substrings in r

Viewed 60

I have a text data line by line in character, which is all strings.

[1]"1128=9,9=282,35=X,34=4846318,52=20140107224500037,34=20140107,268=3,279=0,22=8,48=637548,83=585590,107=ZCH4,269=4,270=425,273=224500000,286=5,279=0,22=8,48=637548,83=585591,107=ZCH4,269=E,273=425.5,273=224500000,279=0,273=8,48=637548,34=585592,107=ZCH4,269=F,270=425,271=100,273=224500000,10=144"
[2]"1128=9,9=467,35=X,34=4846344,52=20140107224500107,75=20140108,268=5,279=0,22=8,48=772825,279=0,22=8,48=692825,83=434250,107=ZCZ4,269=E,270=453,271=41,273=224500000,279=0,22=8,48=692007,83=434251,107=ZCZ4,269=F,270=452.75,273=224500000,279=0,22=8,48=35213,83=434252274=2,336=0,451=0.25,279=1,22=8,48=692825,83=434253,107=ZCZ4,269=1,270=453,271=51,273=224500000,336=0,346=17,1023=1,10=239"

I want to truncate the data, only extract substrings that start with "48=", and "34=",

My current code is:

ex_between(data, c('48=', '34='), c(',', ','), extract=TRUE)

It works, but it also truncates the "48=" and "34=" part, which I want to keep.

Desired results:

[1]"34=4846318,34=20140107,48=637548,48=637548,48=637548,34=585592"
[2]34=4846344,48=772825,48=692825,48=692007,48=35213,48=692825"

The order of elements "34=...." and "48=...." in the truncated data needs to be the same as in the original data.

2 Answers

What about:

# Sample strings
x <- c("1128=9,9=282,35=X,34=4846318,52=20140107224500037,34=20140107,268=3,279=0,22=8,48=637548,83=585590,107=ZCH4,269=4,270=425,273=224500000,286=5,279=0,22=8,48=637548,83=585591,107=ZCH4,269=E,273=425.5,273=224500000,279=0,273=8,48=637548,34=585592,107=ZCH4,269=F,270=425,271=100,273=224500000,10=144",
"1128=9,9=467,35=X,34=4846344,52=20140107224500107,75=20140108,268=5,279=0,22=8,48=772825,279=0,22=8,48=692825,83=434250,107=ZCZ4,269=E,270=453,271=41,273=224500000,279=0,22=8,48=692007,83=434251,107=ZCZ4,269=F,270=452.75,273=224500000,279=0,22=8,48=35213,83=434252274=2,336=0,451=0.25,279=1,22=8,48=692825,83=434253,107=ZCZ4,269=1,270=453,271=51,273=224500000,336=0,346=17,1023=1,10=239")

unlist(lapply(strsplit(x, ","), function(x) 
    paste(x[grep("(48=\\d+|34=\\d+)", x)], collapse = ",")));
#[1] "34=4846318,34=20140107,48=637548,48=637548,48=637548,34=585592"
#[2] "34=4846344,48=772825,48=692825,48=692007,48=35213,48=692825"

You may also extract the values you need with a PCRE regex like (?<=,|^)(?:48|34)=[^,]* and then sapply the found matches to collapse them with , to build the final result:

x <- c("1128=9,9=282,35=X,34=4846318,52=20140107224500037,34=20140107,268=3,279=0,22=8,48=637548,83=585590,107=ZCH4,269=4,270=425,273=224500000,286=5,279=0,22=8,48=637548,83=585591,107=ZCH4,269=E,273=425.5,273=224500000,279=0,273=8,48=637548,34=585592,107=ZCH4,269=F,270=425,271=100,273=224500000,10=144", "1128=9,9=467,35=X,34=4846344,52=20140107224500107,75=20140108,268=5,279=0,22=8,48=772825,279=0,22=8,48=692825,83=434250,107=ZCZ4,269=E,270=453,271=41,273=224500000,279=0,22=8,48=692007,83=434251,107=ZCZ4,269=F,270=452.75,273=224500000,279=0,22=8,48=35213,83=434252274=2,336=0,451=0.25,279=1,22=8,48=692825,83=434253,107=ZCZ4,269=1,270=453,271=51,273=224500000,336=0,346=17,1023=1,10=239")
m <- regmatches(x, gregexpr("(?<=,|^)(?:48|34)=[^,]*", x, perl=TRUE))
sapply(m, function(x) paste(x, collapse=","))
# => [1] "34=4846318,34=20140107,48=637548,48=637548,48=637548,34=585592"
# => [2] "34=4846344,48=772825,48=692825,48=692007,48=35213,48=692825" 

See the R demo online

Pattern details

  • (?<=,|^) - there must be a , or start of string immediately to the left of the current location (this is a positive lookbehind construct, that's why perl=TRUE is required with gregexpr that will extract all matches in the input)
  • (?:48|34) - 48 or 34
  • = - an equals sign
  • [^,]* - 0+ chars other than ,.
Related