常识和使用gregexpr()
进行的理智检查表明,下面的前瞻性和前瞻性断言应该在testString
中的一个位置匹配。
testString <- "text XX text"
BB <- "(?<= XX )"
FF <- "(?= XX )"
as.vector(gregexpr(BB, testString, perl=TRUE)[[1]])
# [1] 9
as.vector(gregexpr(FF, testString, perl=TRUE)[[1]][1])
# [1] 5
然而,strsplit()
以不同的方式使用这些匹配位置,在使用查找后断言时,在one位置拆分testString
,而在使用前瞻性断言时在的两个位置--第二个位置似乎不正确--进行拆分。
strsplit(testString, BB, perl=TRUE)
# [[1]]
# [1] "text XX " "text"
strsplit(testString, FF, perl=TRUE)
# [[1]]
# [1] "text" " " "XX text"
我有两个问题:(Q1),这是怎么回事?(Q2)如何才能让strsplit()
表现得更好呢?
更新: Theodore Lytras的出色回答解释了正在发生的事情,因此提到了(Q1)。我的答案建立在他的基础上,找到了一种补救办法,即寻址(Q2)。
发布于 2013-03-22 12:05:06
我不确定这是否符合错误,因为我认为这是基于R文档的预期行为。来自?strsplit
应用于每个输入字符串的算法是 重复{如果字符串为空中断。如果有匹配,则将匹配的左侧字符串添加到输出中。移除火柴和所有左边的火柴。否则,将字符串添加到输出中。休息一下。} 请注意,这意味着如果在(非空)字符串的开头有匹配,则输出的第一个元素为“”,但如果字符串末尾有匹配,则输出与删除的匹配相同。
问题是,前瞻性(和回顾性)断言是零长度的。例如,在本例中:
FF <- "(?=funky)"
testString <- "take me to funky town"
gregexpr(FF,testString,perl=TRUE)
# [[1]]
# [1] 12
# attr(,"match.length")
# [1] 0
# attr(,"useBytes")
# [1] TRUE
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "take me to " "f" "unky town"
所发生的情况是,孤独的展望(?=funky)
匹配位置12。因此,第一个拆分包含到位置11 (匹配的左边)的字符串,它与匹配一起从字符串中移除,但是匹配的长度为零。
现在剩下的字符串是funky town
,查找位置1匹配。但是没有什么要删除的,因为在匹配的左边没有任何内容,而且匹配本身的长度为零。因此,算法被困在一个无限循环中。显然,R是通过拆分单个字符来解决这一问题的,顺便说一句,这是strsplit
使用空正则表达式(当参数为split=""
)时的记录行为。在此之后,剩下的字符串是unky town
,由于没有匹配,它作为最后一个拆分返回。
查找后向没有问题,因为每个匹配被分割并从剩余的字符串中删除,所以算法永远不会被卡住。
诚然,乍一看,这种行为看起来很奇怪。然而,如果不这样做,就违反了看台长度为零的假设。考虑到strsplit
算法是文档化的,我相信这不符合bug的定义。
发布于 2013-03-22 14:17:02
基于Theodore Lytras对substr()
行为的仔细解释,一个相当干净的解决方法是在即将匹配的前瞻性断言前加上一个与任何单个字符匹配的正向后断言:
testString <- "take me to funky town"
FF2 <- "(?<=.)(?=funky)"
strsplit(testString, FF2, perl=TRUE)
# [[1]]
# [1] "take me to " "funky town"
发布于 2013-03-22 09:36:49
在我看来是个虫子。这似乎不只是与空间有关,特别是,而是任何孤独的展望(积极或消极):
FF <- "(?=funky)"
testString <- "take me to funky town"
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "take me to " "f" "unky town"
FF <- "(?=funky)"
testString <- "funky take me to funky funky town"
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "f" "unky take me to " "f" "unky "
# [5] "f" "unky town"
FF <- "(?!y)"
testString <- "xxxyxxxxxxx"
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "xxx" "y" "xxxxxxx"
如果提供了一些可以与零宽度断言一起捕获的内容,则似乎工作得很好,例如:
FF <- " (?=XX )"
testString <- "text XX text"
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "text" "XX text"
FF <- "(?= XX ) "
testString <- "text XX text"
strsplit(testString,FF,perl=TRUE)
# [[1]]
# [1] "text" "XX text"
也许像这样的东西可以作为一个解决办法。
https://stackoverflow.com/questions/15575221
复制相似问题