R gsub&正则表达式找到价格

时间:2015-11-15 20:42:06

标签: regex r gsub

我正在尝试根据给定的文本创建一个新的价格向量。我只被允许使用gsub

test = c('Testing $26,500\ntesting', 
         'Testing tesing $79+\n TOTAL: $79200', 
         'Testing $3880. Testing', 
         'Testing -$69000Engine: $69000100%',
         'Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5')

期望输出:

# [1] 26500 79200  3880 69000  7495

我尝试了多个正则表达式,但我无法获得正确的结果。

首次尝试:

gsub(".*\\$(\\d+)[,|.](\\d+).*", "\\1\\2", test)
# [1] "26500"                                                               
# [2] "Testing tesing $79+\n TOTAL: $79200"                                 
# [3] "Testing $3880. Testing"                                              
# [4] "Testing -$69000Engine: $69000100%"                                   
# [5] "Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5"

第二次尝试:

gsub(".*\\$(\\d+)[,|.].*", "\\1", test) 
# [1] "26"                                                                  
# [2] "Testing tesing $79+\n TOTAL: $79200"                                 
# [3] "3880"                                                                
# [4] "Testing -$69000Engine: $69000100%"                                   
# [5] "Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5"

第三次尝试:

gsub("(?:.*|.*?*)\\$([0-9]+).*", "\\1", test) 
# [1] "26"                                                                  
# [2] "79200"                                                               
# [3] "3880"                                                                
# [4] "69000100"                                                            
# [5] "Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5"

第四次尝试:

gsub(".*[-]\\$(\\d+).*", "\\1", test) 
# [1] "Testing $26,500\ntesting"                                            
# [2] "Testing tesing $79+\n TOTAL: $79200"                                 
# [3] "Testing $3880. Testing"                                              
# [4] "69000"                                                               
# [5] "Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5"

问题:如何解决此问题并避免使用多个gsub函数调用?

1 个答案:

答案 0 :(得分:4)

我不相信有一种方法只能使用1次gsub来电,因为您需要预先处理数字为"断开连接的最后价格"带空格,第一个用逗号小数分隔符。

我只能"签约" 2 gsub调用的代码:

  • gsub("([$]|(?!^)\\G)[\\s,]*(\\d)", "\\1\\2", test, perl=T)将删除$符号
  • 后面的数字之间的逗号和空格
  • gsub("^(?|[\\s\\S]*-[$](\\d+)|[\\s\\S]*[$](\\d+))[\\s\\S]*$", "\\1", test, perl=T)实际上会从字符串中获得所需的价格编号。

IDEONE demo

test <- c("Testing $26,500\ntesting","Testing tesing $79+\n TOTAL: $79200","Testing $3880. Testing", "Testing -$69000Engine: $69000100%","Testing testing original price : $ 8 2 9 5 . Real price is $ 7 4 9 5")
test <- gsub("([$]|(?!^)\\G)[\\s,]*(\\d)", "\\1\\2", test, perl=T)
test <- gsub("^(?|[\\s\\S]*-[$](\\d+)|[\\s\\S]*[$](\\d+))[\\s\\S]*$", "\\1", test, perl=T)
test

结果:[1] "26500" "79200" "3880" "69000" "7495"

因为你正在学习正则表达式,所以这里是正则表达式分解:

正则表达式1:

  • ([$]|(?!^)\\G) - 匹配并捕获 a&#34;领先的边界&#34;构造匹配$符号,并且每次成功匹配后的位置(?!^)\G\G也匹配字符串的开头,我们用负面预测消除它{{1} })
  • (?!^) - 匹配0个或多个逗号或空格
  • [\\s,]* - 匹配并捕获数字

使用(\\d)替换模式,我们会在字符串中恢复\1\2符号及其后面的数字。

正则表达式2:

  • $ - 字符串的开头
  • ^ - 一个分支重置组(?|[\\s\\S]*-[$](\\d+)|[\\s\\S]*[$](\\d+))),其中捕获组索引重置为1(因此,我们只需要使用(?|...|...)引用在替换模式中,以解决来自每个替代方案的\1匹配....
    • (\\d+) - 任意零个或多个字符([\\s\\S]*-[$](\\d+))后跟一个连字符,然后是[\s\S]*,然后是一个或多个数字($,第1组)
    • \d+ - 或......
    • | - 任意零个或多个字符([\\s\\S]*[$](\\d+))后跟一个[\s\S]*,然后是一个或多个数字($仍为第1组

我们只用\d+反向引用替换所有内容以获取结果。   - \1 - 任何字符,0次或更多次出现([\\s\\S]*$),直到字符串末尾([\s\S]*)。