我正在尝试在某些特定点(短划线,strsplit
)中拆分R中的字符串(使用-
)但是如果短划线位于括号内的字符串内{{1} })。
示例:
[
应该给我一些类似的东西:
xx <- c("Radio Stations-Listened to Past Week-Toronto [FM-CFXJ-93.5 (93.5 The Move)]","Total Internet-Time Spent Online-Past 7 Days")
xx
[1] "Radio Stations-Listened to Past Week-Toronto [FM-CFXJ-93.5 (93.5 The Move)]"
[2] "Total Internet-Time Spent Online-Past 7 Days"
有没有办法用正则表达式来做到这一点?虚线的位置和数量在向量的每个元素内发生变化,并且不总是括号。但是,当有括号时,它们总是在最后。
我尝试了不同的东西,但没有一个在起作用:
list(c("Radio Stations","Listened to Past Week","Toronto [FM-CFXJ-93.5 (93.5 The Move)]"), c("Total Internet","Time Spent Online","Past 7 Days"))
[[1]]
[1] "Radio Stations" "Listened to Past Week"
[3] "Toronto [FM-CFXJ-93.5 (93.5 The Move)]"
[[2]]
[1] "Total Internet" "Time Spent Online" "Past 7 Days"
任何帮助都将不胜感激。
答案 0 :(得分:2)
基于:Regex for matching a character, but not when it's enclosed in square bracket
您可以使用:
importer.ProtocolName = "Soap"; // Woohoo
答案 1 :(得分:2)
要匹配不在-
和[
内的]
,您必须匹配[
和]
附带的字符串的一部分,省略它,并在所有其他上下文中匹配-
。在abc-def]
,-
不在[
和]
之间。不应该对规格进行分割。
完成this regex:
\[[^][]*](*SKIP)(*FAIL)|-
下面,
\[
- 匹配[
[^][]*
- 除[
和]
以外的零个或多个字符(如果您使用[^]]
,它将匹配任何字符,但]
)]
- 文字]
(*SKIP)(*FAIL)
- 省略匹配的PCRE动词,并在省略的一个结束后让引擎继续寻找匹配|
- 或-
- 其他情境中的连字符。 或者,匹配[...[...]
类似子串(demo):
\[[^]]*](*SKIP)(*FAIL)|-
或者,考虑嵌套的方括号(demo):
(\[(?:[^][]++|(?1))*])(*SKIP)(*FAIL)|-
在这里,(\[(?:[^][]++|(?1))*])
匹配并捕获[
,然后是[
和]
以及[^][]++
或(|
以外的1 +个字符} (?1)
递归整个捕获组1模式((...)
之间的整个部分)。
请参阅R demo:
xx <- c("abc-def]", "Radio Stations-Listened to Past Week-Toronto [FM-CFXJ-93.5 (93.5 The Move)]","Total Internet-Time Spent Online-Past 7 Days")
pattern <- "\\[[^][]*](*SKIP)(*FAIL)|-"
strsplit(xx, pattern, perl=TRUE)
# [[1]]
# [1] "abc" "def]"
# [[2]]
# [1] "Radio Stations"
# [2] "Listened to Past Week"
# [3] "Toronto [FM-CFXJ-93.5 (93.5 The Move)]"
# [[3]]
# [1] "Total Internet" "Time Spent Online" "Past 7 Days"
pattern_recursive <- "(\\[(?:[^][]++|(?1))*])(*SKIP)(*FAIL)|-"
xx2 <- c("Radio Stations-Listened to Past Week-Toronto [[F[M]]-CFXJ-93.5 (93.5 The Move)]","Total Internet-Time Spent Online-Past 7 Days")
strsplit(xx2, pattern_recursive, perl=TRUE)
# [[1]]
# [1] "Radio Stations"
# [2] "Listened to Past Week"
# [3] "Toronto [[F[M]]-CFXJ-93.5 (93.5 The Move)]"
# [[2]]
# [1] "Total Internet" "Time Spent Online" "Past 7 Days"
答案 2 :(得分:1)
1)gsubfn 假设方括号是平衡的而不是嵌套的,gsubfn
定位每个[...]并在这些使用gsub
内将短划线转换为感叹号。然后我们将剩余破折号上留下的内容拆分,并用破折号替换感叹号。
正则表达式表示匹配[
后跟最短字符串,直到下一个]
。
library(gsubfn)
s <- strsplit(gsubfn("\\[.*?\\]", ~ gsub("-", "!", x), xx), "-")
lapply(s, gsub, pattern = "!", replacement = "-")
可以使用magrittr管道表示:
library(gsubfn)
library(magrittr)
xx %>%
gsubfn(pattern = "\\[.*?\\]", replacement = ~ gsub("-", "!", x)) %>%
strsplit("-") %>%
lapply(gsub, pattern = "!", replacement = "-")
2)readLines 此替代方案不使用包,不使用strsplit
并仅使用简单的固定正则表达式。它还假设平衡的非嵌套方括号。
使用gsub
首先使用新行(每行使用换行符和后缀)添加新行。然后对于每个输入字符串,它将结果读入r
,对于奇数定位的字符串,用换行替换短划线。最后,它再次将r
粘贴在一起并重新读取它,这会在新行(以前是破折号)中将其拆分。
lapply(gsub("\\]", "]\n", gsub("\\[", "\n[", xx)), function(x) {
r <- readLines(textConnection(x))
i <- seq(1, length(r), 2)
r[i] <- gsub("-", "\n", r[i])
readLines(textConnection(paste(r, collapse = "")))
})