regex.escape <- function(string) {
gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
examples <- 'Text: cm+km, +km and C++,Delphi,C++CLI and C++/CLI.'
words <- c('+km', 'C++')
# Unambiguous word boundaries
regex <- paste0('(?<!\\w)(', paste(regex.escape(words), collapse='|'), ')(?!\\w)')
gsub(regex, "<<\\1>>", examples, perl=TRUE)
# => [1] "Text: cm+km, <<+km>> and <<C++>>,Delphi,C++CLI and <<C++>>/CLI."
# Whitespace boundaries
regex <- paste0('(?<!\\S)(', paste(regex.escape(words), collapse='|'), ')(?!\\S)')
gsub(regex, "<<\\1>>", examples, perl=TRUE)
# => [1] "Text: cm+km, <<+km>> and C++,Delphi,C++CLI and C++/CLI."
cmVnZXguZXNjYXBlIDwtIGZ1bmN0aW9uKHN0cmluZykgewogIGdzdWIoIihbXVt7fSgpKypeJHxcXFxcPy5dKSIsICJcXFxcXFwxIiwgc3RyaW5nKQp9CmV4YW1wbGVzIDwtICdUZXh0OiBjbStrbSwgK2ttIGFuZCBDKyssRGVscGhpLEMrK0NMSSBhbmQgQysrL0NMSS4nCndvcmRzIDwtIGMoJytrbScsICdDKysnKQojIFVuYW1iaWd1b3VzIHdvcmQgYm91bmRhcmllcwpyZWdleCA8LSBwYXN0ZTAoJyg/PCFcXHcpKCcsIHBhc3RlKHJlZ2V4LmVzY2FwZSh3b3JkcyksIGNvbGxhcHNlPSd8JyksICcpKD8hXFx3KScpCmdzdWIocmVnZXgsICI8PFxcMT4+IiwgZXhhbXBsZXMsIHBlcmw9VFJVRSkKIyA9PiBbMV0gIlRleHQ6IGNtK2ttLCA8PCtrbT4+IGFuZCA8PEMrKz4+LERlbHBoaSxDKytDTEkgYW5kIDw8QysrPj4vQ0xJLiIKIyBXaGl0ZXNwYWNlIGJvdW5kYXJpZXMKcmVnZXggPC0gcGFzdGUwKCcoPzwhXFxTKSgnLCBwYXN0ZShyZWdleC5lc2NhcGUod29yZHMpLCBjb2xsYXBzZT0nfCcpLCAnKSg/IVxcUyknKQpnc3ViKHJlZ2V4LCAiPDxcXDE+PiIsIGV4YW1wbGVzLCBwZXJsPVRSVUUpCiMgPT4gWzFdICJUZXh0OiBjbStrbSwgPDwra20+PiBhbmQgQysrLERlbHBoaSxDKytDTEkgYW5kIEMrKy9DTEkuIg==