有选择地删除尾随字符串

Selectively removing trailing string

我想删除最后一个字母 "O",除非它是单词 "HELLO" 的一部分。

我试过这样做:

示例:

a <- c("HELLO XO","DO HELLO","TWO XO","HO")
gsub("[^HELLO]O\>","",a)

[1] "HELLO " " HELLO" "T " "HO"

但我想要

"HELLO X" "D HELLO" "TW X" "H"

尝试使用以下模式替换:

\b(?!HELLO\b)(\w+)O\b

这表示断言单词 HELLO 没有作为单词出现,然后捕获所有内容,直到最后的 O,如果它出现。然后,它替换为删除的可选最终 O

\b          - from the start of the word
(?!HELLO\b) - assert that the word is not HELLO
(\w+)O      - match a word ending in O, but don't capture final O
\b          - end of word

如果发生匹配,捕获组将包含整个单词减去最后的 O。

代码:

a <- c("HELLO XO","DO HELLO","TWO XO","HO")
gsub("\b(?!HELLO\b)(\w+)O\b", "\1", a, perl=TRUE)
[1] "HELLO X" "D HELLO" "TW X"    "H"

请注意,我们必须使用 gsub 启用 Perl 模式 (perl=TRUE) 才能使用负先行。

Demo

使用正则表达式交替运算符|

a <- c("HELLO XO","DO HELLO","TWO XO","HO")
gsub("(HELLO)|O(?!\S)", "\1", a, perl=T)
# [1] "HELLO X" "D HELLO" "TW X"    "H"      

(HELLO)|O 这个正则表达式做了两件事,

  1. 首先它捕获所有 HELLO 字符串。

  2. 匹配所有剩余的 0 后面没有非 space 字符。

a <- c("HELLO XO","DO HELLO","TWO XO","HO")

aa <- gsub("O","",a)
gsub("HELL", "HELLO",aa)

您的正则表达式完全正确。[^HELLO] 表示除 HELO 之外的任何字符。但是你只需要在 O 之前恰好 HELL。因此,您应该使用以下表达式:

a <- c("HELLO XO","DO HELLO","TWO XO","HO")
gsub("(?<!\bHELL)O\b", "", a, perl=TRUE)

有点长,不过你可以这样试试

a <- c("HELLO XO","DO HELLO","TWO XO","HO")
b <- lapply(a, function(x) unlist(strsplit(x, " ")))
b
> b
[[1]]
[1] "HELLO" "XO"   

[[2]]
[1] "DO"    "HELLO"

[[3]]
[1] "TWO" "XO" 

[[4]]
[1] "HO"


c <- unlist(lapply(b, function(y) paste(ifelse( y == "HELLO", "HELLO", gsub("O", "", y)), collapse = " " )))
c

[1] "HELLO X" "D HELLO" "TW X"    "H"