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
我对 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