2015-11-15 62 views
1

我試圖從給定的文本中創建一個新的價格向量。我只能使用gsubR 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

@akrun:不,它不是作業。我已閱讀這篇文章[鏈接](http://stackoverflow.com/questions/31288513/removing-characters-after-a-euro-symbol-in-r)。我試着想出更多的例子來測試它。由於我在R中學習正則表達式,因此我不想用包stringr來嘗試它。 –

+0

你知道你可以複製/粘貼控制檯而不是所有的圖片。您和我們都更輕鬆。 –

+0

@Richard Scriven:我很抱歉給您帶來不便。我只是最近使用了stackoverflow。但是,只有結果是截圖,所有的代碼都在代碼塊中。 –

回答

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) - 匹配和捕獲「龍頭邊界」構建匹配$象徵,每個成功的匹配(?!^)\G後的位置(\G也匹配字符串的開始,我們用負前瞻(?!^)消除它)
  • [\\s,]* - 匹配0或多個逗號或空格
  • (\\d) - 匹配和捕獲一個數字

使用\1\2替換模式,我們將$符號及其後面的數字恢復爲字符串內部的數字。

正則表達式2:

  • ^ - 串
  • (?|[\\s\\S]*-[$](\\d+)|[\\s\\S]*[$](\\d+))的開端 - 一個分支復位組(?|...|...))其中捕獲組索引重置爲1(因此,我們只需要在替換模式中使用參考\1即可解決來自各個替代方案的(\\d+))匹配....
    • [\\s\\S]*-[$](\\d+) - 任何零個或多個字符([\s\S]*),接着以連字符,那麼$,然後1個或多個位(\d+,第1組)
    • | - 或...
    • [\\s\\S]*[$](\\d+) - 任何零個或多個字符([\s\S]*),接着用$然後1個或多個位(\d+仍然組1

而我們用\1反向參考全部替換以獲得我們的結果。 - [\\s\\S]*$ - 任何字符,0次或多次出現([\s\S]*),直到字符串的末尾($)。

+0

謝謝stribizhev。我正在閱讀序列定義,但找不到\\ G在您的正則表達式中的含義1. –

+0

我已經將'\ G'描述爲*每次成功匹配後的位置*和*字符串*的開始。由於我們不想在字符串的開始處進行匹配,因此我們添加負面預讀「(?!^)」。 –