简体   繁体   中英

Regular expression to find and replace conditionally

I need to replace string A with string B, only when string A is a whole word (eg "MECH"), and I don't want to make the replacement when A is a part of a longer string (eg "MECHANICAL"). So far, I have a grepl() which checks if string A is a whole string, but I cannot figure out how to make the replacement. I have added an ifelse() with the idea to makes the gsub() replacement when grep() returns TRUE, otherwise not to replace. Any suggestions? Please see the code below. Thanks.

aa <- data.frame(type = c("CONSTR", "MECH CONSTRUCTION", "MECHANICAL CONSTRUCTION MECH", "MECH CONSTR", "MECHCONSTRUCTION"))

from <- c("MECH", "MECHANICAL", "CONSTR",  "CONSTRUCTION")
to <- c("MECHANICAL", "MECHANICAL", "CONSTRUCTION", "CONSTRUCTION")

gsub2 <- function(pattern, replacement, x, ...) {
  for(i in 1:length(pattern)){
    reg <- paste0("(^", pattern[i], "$)|(^", pattern[i], " )|( ", pattern[i], "$)|( ", pattern[i], " )")
    ifelse(grepl(reg, aa$type),
           x <- gsub(pattern[i], replacement[i], x, ...),
           aa$type)
  }
  x
}

aa$title3 <- gsub2(from, to, aa$type)

You can enclose the strings in the from vector in \\\\< and \\\\> to match only whole words:

x <- c("CONSTR", "MECH CONSTRUCTION", "MECHANICAL CONSTRUCTION MECH", 
       "MECH CONSTR", "MECHCONSTRUCTION")

from <- c("\\<MECH\\>", "\\<CONSTR\\>")
to <- c("MECHANICAL", "CONSTRUCTION")

for(i in 1:length(from)){
  x <- gsub(from[i], to[i], x)
}

print(x)
# [1] "CONSTRUCTION"                       "MECHANICAL CONSTRUCTION"           
# [3] "MECHANICAL CONSTRUCTION MECHANICAL" "MECHANICAL CONSTRUCTION"           
# [5] "MECHCONSTRUCTION"

I use regex (?<=\\W|^)MECH(?=\\W|$) to get if inside the string contain whole word MECH like this .

Is that what you need?

Just for posterity, other than using the \\< \\> enclosure, a whole word can be defined as any string ending in a space or end-of-line ( \\s|$ ).

gsub("MECH(\\s|$)", "MECHANICAL\\1", aa$type)

The only problem with this approach is that you need to carry over the space or end-of-line that you used as part of the match, hence the encapsulation in parentheses and the backreference ( \\1 ).

The \\< \\> enclosure is superior for this particular question, since you have no special exceptions. However, if you have exceptions, it is better to use a more explicit method. The more tools in your toolbox, the better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM