R在所有单词周围加上引号,除了某个单词

时间:2015-03-22 05:38:25

标签: regex r replace regex-lookarounds

我正在尝试使用gsub函数在所有单词周围放置单引号,除非单词" one"。我已经尝试了以下但是它没有像我预期的那样工作。

text <- "one two three four five one six one seven one eight nine ten one"
gsub("(?<!one)([a-zA-Z]+)", "'\\1'", text)

输出应为:

one 'two' 'three' 'four' 'five' one 'six' one 'seven' one 'eight' 'nine' 'ten' one

感谢任何帮助。

4 个答案:

答案 0 :(得分:2)

对于初学者,(?<!...) PCRE ,其中需要启用perl = TRUE参数。

诀窍是在这里使用lookahead而不是lookbehind并添加word boundaries来强制正则表达式引擎匹配整个单词。另外,你大致说明了单词;在我的词汇表中,这可能意味着任何类型的单词,所以我将使用Unicode属性\pL,它匹配来自任何语言的任何类型的字母,如果这匹配超过预期,您可以简单地将其更改回{{ 1}}或者使用名为class [a-zA-Z]的POSIX代替。

[[:alpha:]]

答案 1 :(得分:1)

您可以尝试下面的PCRE正则表达式

> gsub('\\bone\\b(*SKIP)(*F)|([A-Za-z]+)', "'\\1'", text, perl=TRUE)
[1] "one 'two' 'three' 'four' 'five' one 'six' one 'seven' one 'eight' 'nine' 'ten' one"

\\bone\\b与文字one匹配,以下(*SKIP)(*F)会使匹配跳过然后失败。现在它使用|运算符右侧的模式从剩余的字符串中选择字符(即,跳过的部分除外)

DEMO

答案 2 :(得分:1)

这是一种分步进行的方法。首先引用每个单词,然后从你不想引用的单词中删除引号。它可能会解决您的需求,但可能需要对标点符号进行一些额外的微调。

test <- paste0("'", text, "'")
test <- gsub(" ", "' '", test)
test <- gsub("'one'", "one", test)

答案 3 :(得分:1)

使用正则表达式似乎很奇怪。如果你有更复杂的表达式,也许这样的东西会起作用(并且会更具可读性)。

# for piping and equals() and not()
library(magrittr)

#helper function
partialswap <- function(x, criteria, transform) {
    idx<-criteria(x)
    x[idx]<-transform(x[idx])
    x
}
not_equals <- function(x) . %>% equals(x) %>% not
is_not_in <- function(x) . %>% is_in(x) %>% not

text <- "one two three four five one six one seven one eight nine ten one"
strsplit(text, " ")[[1]] %>% 
    partialswap(not_equals("one"), shQuote) %>% 
    paste(collapse=" ")
# [1] "one 'two' 'three' 'four' 'five' one 'six' one 'seven' one 'eight' 'nine' 'ten' one"

或者,如果你想离开&#34;一个&#34;和&#34;三&#34;

strsplit(text, " ")[[1]] %>% 
    partialswap(is_not_in(c("one","three")), shQuote) %>% 
    paste(collapse=" ")
# [1] "one 'two' three 'four' 'five' one 'six' one 'seven' one 'eight' 'nine' 'ten' one"