strsplit 令人费解的行为中的负面前瞻

Negative lookahead in strsplit puzzling behaviour

我对 R v3.6.2 中 strsplit 中的一个简单前瞻行为感到困惑:当我尝试匹配 space (</code>) <em>not </em> 后跟正斜杠 (<code>/) 正则表达式的行为很奇怪。

下面的尝试正确地没有使用正斜杠,但之后仍然在 space 处拆分。输出与模式相同:' (?!/ )'' (?!/ *)',以及其他通配符 .?

strsplit(c("foo1 foo2", "foo1 / foo2", "foo1/foo2"), ' (?!/)', perl = T)
[[1]]
[1] "foo1" "foo2"

[[2]]
[1] "foo1 /" "foo2"  

[[3]]
[1] "foo1/foo2"

这更加令人困惑,因为如果我否定正向前瞻,strsplit 将不会拆分任何内容。如上所述,这会以不同的模式持续存在。

strsplit(c("foo1 foo2", "foo1 / foo2", "foo1/foo2"), ' ^(?=/)', perl = T)
[[1]]
[1] "foo1 foo2"

[[2]]
[1] "foo1 / foo2"

[[3]]
[1] "foo1/foo2"

转义正斜杠(无论如何都不应该是特殊字符)会产生相同的结果。

所需的输出应如下所示:

[[1]]
[1] "foo1" "foo2"

[[2]]
[1] "foo1 / foo2"  

[[3]]
[1] "foo1/foo2"

抱歉,如果这是非常基本的,但我找不到针对此特定行为的解释。

您的 original regex 不适合您,因为 spaces after / 仍然匹配。 (?!/) 匹配任何未直接跟随 / 的 space,但如果它前面有 /.

,则不匹配

您可以尝试 (?<!/) (?!/) - 参见 this regex demo,但这仍然会匹配 / 之前或 / 之后的 space。

为了匹配任何 1+ 个 whitespace 字符,但是当 whitespace 包含一个 / 字符时,您可以使用

strsplit(c("foo1 foo2", "foo1 / foo2", "foo1/foo2"), '\s*/\s*(*SKIP)(*F)|\s+', perl=TRUE)

\s*/\s*(*SKIP)(*F)|\s+(参见its online demo)模式匹配

  • \s*/\s*(*SKIP)(*F) - 消耗 1+ whitespaces,/ 然后 1+ whitespaces 并丢弃 match
  • | - 或
  • \s+ - 消耗 1+ 白色spaces