2016-12-29 68 views
1

我意识到这是一个相当简单的问题定义边界和我已经搜索整个网站,但似乎无法让我的语法正确以下的正则表达式的挑战。我期待着做两件事。首先有正则表达式拿起前三个字符,并以分号停止。例如,我的字符串可能如下:正则表达式 - 用文字和分隔符

Apt;House;Condo;Apts; 

我想在这里去

Apartment;House;Condo;Apartment 

我也想创建一个正则表达式替换的分隔符之间的字,而保持其他人不变。例如,我想从这个去:

feline;labrador;bird;labrador retriever;labrador dog; lab dog; 

要这样:

feline;dog;bird;dog;dog;dog; 

下面是我的工作正则表达式。我知道^表示字符串的开始和$结束。我尝试过许多变化,并想提出换人,但我没有达到我的期望了放。我也猜测一个正则表达式可以为两者工作?谢谢大家的帮助。

df$variable <- gsub("^apt$;", "Apartment;", df$variable, ignore.case = TRUE) 
+1

你想替换整个单词吗?使用单词边界。 'gsub(“\\ bapt \\ b”,“Apartment”,df $ variable,ignore.case = TRUE)'。或者您是否需要专门替换分号和字符串的开始/结尾之间的子字符串? –

+0

我认为你应该删除正则表达式并使用面向字符串的函数。 –

+0

Hi @WiktorStribiżew,我正在寻找替换分号之间的子串以及字符串前面的单词。为了详细说明第二个例子,可以用许多不同的方式发布拉布拉多,包括拉布拉多猎犬,拉布拉多犬,实验室狗等。总之,我需要创建正则表达式,以识别开始时的前三个字符和结束时的分隔符。希望这是有道理的。谢谢。 – BlueDevilPride

回答

3

下面是一个使用向后看(所以你需要perl=TRUE)的方法:

> tmp <- c("feline;labrador;bird;labrador retriever;labrador dog; lab dog;", 
+   "lab;feline;labrador;bird;labrador retriever;labrador dog; lab dog") 
> gsub("(?<=;|^) *lab[^;]*", "dog", tmp, perl=TRUE) 
[1] "feline;dog;bird;dog;dog;dog;" 
[2] "dog;feline;dog;bird;dog;dog;dog" 

(?<=;|^)是背后的样子,它说,任何比赛必须由分号或开始时先的字符串,但匹配的内容不包含在要替换的部分中。该*将匹配0或多个空格(因为你的示例串有在那里有分号和lab之间空间中的一个的情况。然后,它相匹配的文字lab随后比分号其他0或多个字符。由于*是默认的贪婪,这将匹配一切达,但不包括”下一个分号或字符串的结尾。你也可以包括正前瞻(?=;|$),以确保它会一路到下一个半结肠或字符串的结尾,但是在这种情况下*贪婪将采取照顾。

你也可以使用非贪婪的修改,然后强制匹配,结束串或分号:

> gsub("(?<=;|^) *lab.*?(?=;|$)", "dog", tmp, perl=TRUE) 
[1] "feline;dog;bird;dog;dog;dog;" 
[2] "dog;feline;dog;bird;dog;dog;dog" 

.*?将匹配0个或多个字符,但很少,因为它可以得到一直延伸到下一个分号或行尾。

你可以跳过后面的样子(和perl=TRUE)如果你匹配的分隔符,然后将其包含在更换:

> gsub("(;|^) *lab[^;]*", "\\1dog", tmp) 
[1] "feline;dog;bird;dog;dog;dog;" 
[2] "dog;feline;dog;bird;dog;dog;dog" 

有了这个方法,你必须要小心,你只能在一个匹配的分隔符(我的例子中是第一个),因为匹配会消耗分隔符(而不是前瞻或后退),如果你使用了两个分隔符,那么下一个将被跳过,并且只有每隔一个字段才会被替换。

+0

这是辉煌的,完美的作品@Greg Snow!谢谢!不知道看后面。欣赏您提供此解决方案的时间。 – BlueDevilPride

1

我会分两步推荐这样做:

  1. 分割字符串由分隔符
  2. 完成替换
  3. (可选,如果这是你必须做什么)砸烂串起来。

要分割字符串,我会使用stringr库。但是你可以使用基础R太:

myString <- "Apt;House;Condo;Apts;" 

# base R 
splitString <- unlist(strsplit(myString, ";", fixed = T)) 

# with stringr 
library(stringr) 
splitString <- as.vector(str_split(myString, ";", simplify = T)) 

一旦你做到了这一点,那么你可以做的文本替换:

# base R 
fixedApts <- gsub("^Apt$|^Apts$", "Apartment", splitString) 

# with stringr 
fixedApts <- str_replace(splitString, "^Apt$|^Apts$", "Apartment") 

# then do the rest of your replacements 

有probabably一个更好的方式做比正则表达式替换(使用switch(),也许?)

使用paste0(fixedApts, collapse = "")在最后如果这是你需要做的事情将矢量折叠成单个字符串。