Regex to detect consecutive lower and uppercase

Viewed 236

I have character vectors similar to this one:

test <- "ThisisAtest"

I would like to insert a ; between lowercase and uppercase characters, so that the expected output is:

"Thisis;Atest"

To do so, I need to detect the consecutive lowercase and uppercase characters. I tried to do this (I used str_remove instead str_replace because I don't know the first pattern yet):

stringr::str_remove(test, "^[a-zA-Z]*$")

but it returns an empty character vector. Does anyone know how to do this?

I don't know if there are differences between the regex used by gsub() or stringr::str_* functions but I would prefer the latter.

4 Answers

You could also find the position between a lowercase char and an uppercase char using gsub and positive lookarounds without the anchors ^ and $

test <- "ThisisAtest"
gsub("(?<=[a-z])(?=[A-Z])", ";", test, perl=T)

See an R demo

Output

[1] "Thisis;Atest"

One more fully Unicode-aware option is

stringr::str_replace_all(test, '(?<=\\p{Ll})(?=\\p{Lu})', ';')

Explanation

--------------------------------------------------------------------------------
  (?<=                     look behind to see if there is:
--------------------------------------------------------------------------------
    \\p{Ll}                Lowercase Unicode letter
--------------------------------------------------------------------------------
  )                        end of look-behind
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    \\p{Lu}                Uppercase Unicode letter
--------------------------------------------------------------------------------
  )                        end of look-ahead

We can use two capture groups here, one with lower case letter and another one which is immediately followed by upper case and put a semicolon in between.

Note that I have changed the string to include two occurrences of the pattern.

test <- "ThisisAtestAnew"

gsub('([a-z])([A-Z])', '\\1;\\2', test)
[1] "Thisis;Atest;Anew"

This is similar to using str_replace_all in stringr :

stringr::str_replace_all(test, '([a-z])([A-Z])', '\\1;\\2')

Another take: Upper case letter followed for characters until another upper character, we are adding a ';' between two groups.

> test <- "ThisisAtest"
> gsub('([A-Z].*)([A-Z].*)','\\1;\\2',test)
[1] "Thisis;Atest"
> 
Related