我有一个非常凌乱的字符串向量。这是一个例子:
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行所示。
我怀疑我可以使用更多hacky方法来做到这一点,例如获取所有NA
并在Excel或其他东西中手动修复,但我很惊讶我无法弄清楚如何返回一个不匹配的部分尽管有一堆搜索并尝试使用包含(^)
和[^]
的不同正则表达式,但一般来说都是字符串。有什么想法吗?
答案 0 :(得分: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 :(得分: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:13
或13:52:1
。这两种情况都可以通过对正则表达式的简单修改来完成,但正如@Zach所述,没有自动方式。
答案 2 :(得分: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