I want to add a space between two punctuation characters (+ and -). I have this code:
s <- "-+"
str_replace(s, "([:punct:])([:punct:])", "\\1\\s\\2")
It does not work. May I have some help?
I want to add a space between two punctuation characters (+ and -). I have this code:
s <- "-+"
str_replace(s, "([:punct:])([:punct:])", "\\1\\s\\2")
It does not work. May I have some help?
There are several issues here:
[:punct:]
pattern in an ICU regex flavor does not match math symbols (\p{S}
), it only matches punctuation proper (\p{P}
), if you still want to match all of them, combine the two classes, [\p{P}\p{S}]
"\\1\\s\\2"
replacement contains a \s
regex escape sequence, and these are not supported in the replacement patterns, you need to use a literal spacestr_replace
only replaces one, first occurrence, use str_replace_all
to handle all matches-+?/
. You need to make the second part of the regex a zero-width assertion, a positive lookahead, in order not to consume the second punctuation.So, you can use
library(stringr)
s <- "-+?="
str_replace_all(s, "([\\p{P}\\p{S}])(?=[\\p{P}\\p{S}])", "\\1 ")
str_replace_all(s, "(?<=[\\p{P}\\p{S}])(?=[\\p{P}\\p{S}])", " ")
gsub("(?<=[[:punct:]])(?=[[:punct:]])", " ", s, perl=TRUE)
See the R demo online, all three lines yield [1] "- + ? ="
output.
Note that in PCRE regex flavor (used with gsub
and per=TRUE
) the POSIX character class must be put inside a bracket expression, hence the use of double brackets in [[:punct:]]
.
Also, (?<=[[:punct:]])
is a positive lookbehind that checks for the presence of its pattern immediately on the left, and since it is non-consuming there is no need of any backreference in the replacement.