在 R 中的 ls(pattern = "") 中使用负前瞻
Using negative lookahead in ls(pattern = "") in R
假设我在内存中有以下对象:
ab
ab_b
ab_pm
ab_pn
c1_ab_b
我只想保留 ab_pm
和 ab_pn
。
我尝试在 ls()
中使用否定前瞻来列出 ab
、ab_b
和 c1_ab_b
以进行删除:
rm(list = ls(pattern = "ab_?(?!p)")
但是,我得到了错误:
Error in grep(pattern, all.names, value = TRUE) :
invalid regular expression 'ab_?(?!p)', reason 'Invalid regexp'
我在 regex101.com 尝试了我的正则表达式,发现它匹配所有五个对象名称,这表明我的正则表达式不是“无效的”,尽管它没有达到我想要的效果。我的问题是:
- R 中的
ls()
是否支持负前瞻?我知道 grep()
需要 perl = TRUE
来支持它,但在 ls()
帮助文档中没有看到类似的论点。
- 如何正确select我要删除的三个对象?
由于回溯,您的 ab_?(?!p)
PCRE 正则表达式与预期不匹配。它匹配 ab
,然后匹配可选的 _
,然后尝试否定环视。当 lookaround 发现 p
发生回溯时,lookahead 在 _
之前再次触发。由于 _
不是 p
,因此返回匹配项。
正确的 PCRE 正则表达式是 ab(?!_?p)
,请参阅 regex demo。匹配 b
后,正则表达式引擎仅尝试先行模式一次,如果它无法匹配可选的 _
后跟 p
,整个匹配将失败。
ls
不支持perl=TRUE
,所以只支持不支持lookarounds的默认TRE正则库
您可以使用
ab([^_]p|_[^p]|.?$)
参见regex demo。 详情:
ab
- ab
文字
([^_]p|_[^p]|.?$)
- 三种选择之一:
[^_]p
- 除了 _
和 p
之外的任何字符
|
- 或
_[^p]
- 一个 _
然后是除 p
之外的任何字符
|
- 或
.?$
- 任意一个可选字符,然后是字符串结尾。
ls
使用 grep(pattern, all.names, value = TRUE)
,因此它不支持包括 lookahead 在内的 perl 扩展。不过,您可以通过将 ls
包装在 grep
:
中来在外部处理该问题
vec <- ls(pattern = "^ab_")
# vec <- c("ab","ab_b","ab_pm","ab_pn","c1_ab_b")
grep("ab_(?=p)", vec, perl = TRUE, value = TRUE)
# [1] "ab_pm" "ab_pn"
所以也许是一行:
grep("ab_(?=p)", ls(pattern = "^ab_"), value = TRUE, perl = TRUE)
这是一个双重 grep
(一次在里面 ls
,一次在外面);人们总是可以通过
让它更直接一点
grep("ab_(?=p)", ls(), value = TRUE, perl = TRUE)
假设我在内存中有以下对象:
ab
ab_b
ab_pm
ab_pn
c1_ab_b
我只想保留 ab_pm
和 ab_pn
。
我尝试在 ls()
中使用否定前瞻来列出 ab
、ab_b
和 c1_ab_b
以进行删除:
rm(list = ls(pattern = "ab_?(?!p)")
但是,我得到了错误:
Error in grep(pattern, all.names, value = TRUE) :
invalid regular expression 'ab_?(?!p)', reason 'Invalid regexp'
我在 regex101.com 尝试了我的正则表达式,发现它匹配所有五个对象名称,这表明我的正则表达式不是“无效的”,尽管它没有达到我想要的效果。我的问题是:
- R 中的
ls()
是否支持负前瞻?我知道grep()
需要perl = TRUE
来支持它,但在ls()
帮助文档中没有看到类似的论点。 - 如何正确select我要删除的三个对象?
由于回溯,您的 ab_?(?!p)
PCRE 正则表达式与预期不匹配。它匹配 ab
,然后匹配可选的 _
,然后尝试否定环视。当 lookaround 发现 p
发生回溯时,lookahead 在 _
之前再次触发。由于 _
不是 p
,因此返回匹配项。
正确的 PCRE 正则表达式是 ab(?!_?p)
,请参阅 regex demo。匹配 b
后,正则表达式引擎仅尝试先行模式一次,如果它无法匹配可选的 _
后跟 p
,整个匹配将失败。
ls
不支持perl=TRUE
,所以只支持不支持lookarounds的默认TRE正则库
您可以使用
ab([^_]p|_[^p]|.?$)
参见regex demo。 详情:
ab
-ab
文字([^_]p|_[^p]|.?$)
- 三种选择之一:[^_]p
- 除了_
和p
之外的任何字符
|
- 或_[^p]
- 一个_
然后是除p
之外的任何字符
|
- 或.?$
- 任意一个可选字符,然后是字符串结尾。
ls
使用 grep(pattern, all.names, value = TRUE)
,因此它不支持包括 lookahead 在内的 perl 扩展。不过,您可以通过将 ls
包装在 grep
:
vec <- ls(pattern = "^ab_")
# vec <- c("ab","ab_b","ab_pm","ab_pn","c1_ab_b")
grep("ab_(?=p)", vec, perl = TRUE, value = TRUE)
# [1] "ab_pm" "ab_pn"
所以也许是一行:
grep("ab_(?=p)", ls(pattern = "^ab_"), value = TRUE, perl = TRUE)
这是一个双重 grep
(一次在里面 ls
,一次在外面);人们总是可以通过
grep("ab_(?=p)", ls(), value = TRUE, perl = TRUE)