2017-10-13 162 views
3

我有一個非常混亂的字符串矢量。這裏有一個例子:如何使用正則表達式提取R中字符串的不匹配部分?

library(tidyverse) 
library(stringr) 
strings <- tibble(
    name = c("lorem 11:07:59 86136-1-sed", 
      "ipsum 14:35:57 S VARNAME-ut", 
      "dolor 10:37:53 1513 -2-perspiciatis", 
      "sit 10:48:25", 
      "amet 13:52:1365293-2-unde", 
      "consectetur 11:53:1 16018-2-omnis", 
      "adipiscing 11:19 17237-2-iste" 
      ) 
) 
strings_out <- strings %>% 
    mutate(heads = str_extract(name, "^.*?\\s\\d{1,2}:\\d{1,2}:\\d{1,2}")) %>% 
    mutate(ends = str_replace(name, "^.*?\\s\\d{1,2}:\\d{1,2}:\\d{1,2}", "")) 
strings_out[,2:3] 
#> # A tibble: 7 x 2 
#>     heads       ends 
#>     <chr>       <chr> 
#> 1  lorem 11:07:59     86136-1-sed 
#> 2  ipsum 14:35:57     S VARNAME-ut 
#> 3  dolor 10:37:53   1513 -2-perspiciatis 
#> 4  sit 10:48:25        
#> 5  amet 13:52:13     65293-2-unde 
#> 6 consectetur 11:53:1     16018-2-omnis 
#> 7    <NA> adipiscing 11:19 17237-2-iste 

所以在這裏我有一些特色的文字,隨後可能會或可能不會被正確輸入,然後一些文本時間字符串。我想在時間之後提取字符串的末尾,但是他們沒有任何似乎與使用str_extract的潛在正則表達式很好地對應的任何模式。我可以很容易地匹配前半部分的字符串,如heads所示。但是,我發現提取後半部分的唯一方法是使用空字符串str_replace,如ends所示。

我試圖包含我在這個列表中注意到的所有常見錯誤:在時間之後沒有連字符,間隔或字符串內容的模式,沒有時間和字符串的期望的結尾一半之間的保證空間,次數缺少數字甚至冒號。

我想要做的就是能夠使用str_extract來獲得與我通過str_replace得到的東西接近的東西。關鍵的區別是,這裏這個表達式仍然不能正常工作的錯誤,str_extract給我的NA,很容易篩選和手動修復,但str_replace只是整個字符串拷貝中在第7行

我看到懷疑我可以用一些更加棘手的方法來做到這一點,比如獲取所有NA並在Excel中手動修復或某些內容,但我很驚訝我無法找出如何返回字符串中不匹配的部分,儘管有大量搜索並嘗試使用不同的正則表達式,包括(^)[^]。有任何想法嗎?

+2

什麼是理想的結果呢? –

+0

很抱歉,如果不清楚。期望的結果是第二列,除了在第一列有一個的地方返回NA以外。我意識到我可以用正確的索引來代替它們,但是我發現令人費解的是,「返回字符串中無法比擬的部分」的概念似乎很難做到。 –

回答

1

一般而言,您可能會想要查看lookarounds,但您的數據可能需要更多結構才能使其有用。

下面是一個簡單的例子,我認識的時間並不總是加上一個空格前寫道:


library(tidyverse) 
library(stringr) 
strings <- tibble(
    name = c("lorem 11:07:59 86136-1-sed", 
      "ipsum 14:35:57 S VARNAME-ut", 
      "dolor 10:37:53 1513 -2-perspiciatis", 
      "sit 10:48:25", 
      "amet 13:52:1365293-2-unde", 
      "consectetur 11:53:1 16018-2-omnis", 
      "adipiscing 11:19 17237-2-iste" 
) 
) 
strings_out <- strings %>% 
    mutate(heads = str_extract(name, "^.*?\\s\\d{1,2}:\\d{1,2}:\\d{1,2}"), 
     ends = str_extract(name, "(?<=:\\d{1,2})[\\s\\S]+$")) 

strings_out[c(1,3)] 
#> # A tibble: 7 x 2 
#>         name     ends 
#>         <chr>    <chr> 
#> 1   lorem 11:07:59 86136-1-sed   86136-1-sed 
#> 2   ipsum 14:35:57 S VARNAME-ut   S VARNAME-ut 
#> 3 dolor 10:37:53 1513 -2-perspiciatis 1513 -2-perspiciatis 
#> 4      sit 10:48:25     <NA> 
#> 5   amet 13:52:1365293-2-unde     <NA> 
#> 6 consectetur 11:53:1 16018-2-omnis  16018-2-omnis 
#> 7  adipiscing 11:19 17237-2-iste   17237-2-iste 

這裏的問題是像線5線沒有更多的結構,我們無法知道時間是13:52:13還是13:52:1,因爲兩者都是其他字符串中的選項。弄清楚哪個是正確的不是可以用正則表達式解決的問題。

+1

嗯好的我明白你對第5行的意思了。據我所知,當時間後面跟着數字時,它們不會超過五個,這就是我爲什麼寫這個正則表達式的原因。我認爲lookbehind是一個我以前不知道的工具,它允許按照我的意願使用'str_extract'。我想可能沒有一種好的方法來「提取無與倫比的,它只是需要修改正則表達式找到所需的匹配? –

1

你也可以試試這個:

library(tidyverse) 
library(stringr) 

regex = "^\\w+\\s\\d{2}:\\d{2}:*\\d{0,2}" 

strings %>% 
    mutate(head = str_extract(name, regex), 
     end = str_replace(name, paste0(regex, "\\s?"), ""), 
     end = str_replace(end, "^\\s*$", NA_character_)) 

結果:

# A tibble: 7 x 3 
           name    head     end 
           <chr>    <chr>    <chr> 
1   lorem 11:07:59 86136-1-sed  lorem 11:07:59   86136-1-sed 
2   ipsum 14:35:57 S VARNAME-ut  ipsum 14:35:57   S VARNAME-ut 
3 dolor 10:37:53 1513 -2-perspiciatis  dolor 10:37:53 1513 -2-perspiciatis 
4      sit 10:48:25  sit 10:48:25     <NA> 
5   amet 13:52:1365293-2-unde  amet 13:52:13   65293-2-unde 
6 consectetur 11:53:1 16018-2-omnis consectetur 11:53:1  16018-2-omnis 
7  adipiscing 11:19 17237-2-iste adipiscing 11:19   17237-2-iste 

注:

我的解決方案適用於第5行,但你將不得不決定是否在這種情況下,您想提取13:52:1313:52:1。這兩種情況都可以通過對正則表達式的簡單修改來完成,但正如@Zach所述,沒有自動方式。

0

你可以只用一個附加的線路有它:

strings["rx"] <- str_match(strings$name, "\\d*:\\d*(?::\\d+)?(.*)")[,2] 
strings 

其中產量

# A tibble: 7 x 2 
           name     rx 
           <chr>     <chr> 
1   lorem 11:07:59 86136-1-sed   86136-1-sed 
2   ipsum 14:35:57 S VARNAME-ut   S VARNAME-ut 
3 dolor 10:37:53 1513 -2-perspiciatis 1513 -2-perspiciatis 
4      sit 10:48:25      
5   amet 13:52:1365293-2-unde    -2-unde 
6 consectetur 11:53:1 16018-2-omnis   16018-2-omnis 
7  adipiscing 11:19 17237-2-iste   17237-2-iste 
+0

行5呢? – useR