2016-03-07 26 views
0

我遇到了一个看似简单的问题,但我找到的解决方案并不令人满意。我想用逗号替换后面的数字。例如,替换数字后的句点

strings <- c("22.222.222", "12.323", "don.t replace") 

将被成功地转化为

[1] "22,222,222" "12,323"  "don.t replace" 

我尝试的第一个解决方案是

str_replace_all(strings, 
       "(?<=\\d+)\\.", 
       ",") 

,但我得到了以下错误消息:

Error in stri_replace_all_regex(string, pattern, replacement, vectorize_all = vec, : 
Look-Behind pattern matches must have a bounded maximum length. (U_REGEX_LOOK_BEHIND_LIMIT) 

当我使用

str_replace_all(strings, 
      "(?<=\\d{1,3})\\.", 
      ",") 

我得到正确的转换。然而,硬编码的1-3位不是我想要的,我不明白为什么\\d+不起作用,但\\d{1,3}

+1

不是'“(?<= \\ d)\\。”'够好吗? – sgibb

+0

为什么你需要向前看?我的意思是你接受了一个前瞻解决方案的答案,而这实际上不是你在这里需要的。在性能方面,后视是昂贵的(至少在模式开始时),你应该尽可能地避免它们。请注意,限制已经使用的子字符串的lookbehinds是有效的,但事实并非如此。 –

回答

2

不需要+量词,你所关心的只是匹配序列中的最后一位数字。所以只需在\d的后面。

str_replace_all(strings, 
       "(?<=\\d)\\.", 
       ",") 
2

由于数字是已知的子模式,因此不需要任何替代方法,因此不需要任何重叠匹配。只需使用一个捕获组围绕数字和结果与反向引用恢复它们:

> library(stringr) 
> strings <- c("22.222.222", "12.323", "don.t replace") 
> str_replace_all(strings, "(\\d+)\\.", "\\1,") 
[1] "22,222,222" "12,323"  "don.t replace" 

或者与基础R gsub

> gsub("(\\d+)\\.", "\\1,", strings) 
[1] "22,222,222" "12,323"  "don.t replace" 

regex demo

注意(?<=\\d{1,3})约束宽度后视工程,因为stringr正则表达式的风格是ICU 。如果可以事先计算lookbehind中的模式长度,那么它将起作用,因此限制量词具有最小值和最大值都可以正常工作。它不适用于PCRE(perl=T)与gsub正则表达式。无限宽的lookbehind(内部有+*量词)仅在少数几个版本中受支持:Python PyPi正则表达式模块,.NET,RegexBuddy工具,Vim。