在 R 中的 ls(pattern = "") 中使用负前瞻

Using negative lookahead in ls(pattern = "") in R

假设我在内存中有以下对象:

ab
ab_b
ab_pm
ab_pn
c1_ab_b

我只想保留 ab_pmab_pn

我尝试在 ls() 中使用否定前瞻来列出 abab_bc1_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 尝试了我的正则表达式,发现它匹配所有五个对象名称,这表明我的正则表达式不是“无效的”,尽管它没有达到我想要的效果。我的问题是:

  1. R 中的 ls() 是否支持负前瞻?我知道 grep() 需要 perl = TRUE 来支持它,但在 ls() 帮助文档中没有看到类似的论点。
  2. 如何正确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)