是否有 R 函数可以转义正则表达式字符的字符串

Is there an R function to escape a string for regex characters

提问人:Corvus 提问时间:2/13/2013 最后编辑:CommunityCorvus 更新时间:2/10/2022 访问量:11732

问:

我想构建一个正则表达式来替换一些要搜索的字符串,因此需要先对这些字符串进行转义,然后才能将它们放入正则表达式中,以便如果搜索的字符串包含正则表达式字符,它仍然有效。

有些语言有函数可以为你做到这一点(例如python:https://stackoverflow.com/a/10013356/1900520)。R有这样的功能吗?re.escape

例如(组成函数):

x = "foo[bar]"
y = escape(x) # y should now be "foo\\[bar\\]"
正则表达式 字符串 R

评论

0赞 Adam Hyland 2/13/2013
你能添加一个示例字符串以及你希望输出是什么样子吗?
5赞 Dason 2/13/2013
大多数正则表达式函数都有一个称为“fixed”的参数,如果将其设置为 TRUE,将导致模式按原样匹配。
1赞 Corvus 2/13/2013
这不好 - 我想根据用户给出的输入构建一个正则表达式 - 所以我需要“清理”输入,但仍然使用正则表达式。
0赞 Corvus 2/13/2013
我敢肯定我刚才看到了一个很好的答案,但它已经消失了......
0赞 Jeffrey Girard 11/3/2020
与 Dason 的回答相关,参见 stringr::fixed()

答:

20赞 Dason 2/13/2013 #1

显然,在 Hmisc 包中调用了一个函数。该函数本身对输入值“string”具有以下定义:escapeRegex

gsub("([.|()\\^{}+$*?]|\\[|\\])", "\\\\\\1", string)

我之前的回答:

我不确定是否有内置函数,但您可以制作一个来做您想做的事。这基本上只是创建一个你要替换的值的向量和一个你想用什么替换它们的值的向量,然后循环访问那些进行必要替换的值。

re.escape <- function(strings){
    vals <- c("\\\\", "\\[", "\\]", "\\(", "\\)", 
              "\\{", "\\}", "\\^", "\\$","\\*", 
              "\\+", "\\?", "\\.", "\\|")
    replace.vals <- paste0("\\\\", vals)
    for(i in seq_along(vals)){
        strings <- gsub(vals[i], replace.vals[i], strings)
    }
    strings
}

一些输出

> test.strings <- c("What the $^&(){}.*|?", "foo[bar]")
> re.escape(test.strings)
[1] "What the \\$\\^&\\(\\)\\{\\}\\.\\*\\|\\?"
[2] "foo\\[bar\\]"  

评论

0赞 Ryan C. Thompson 2/13/2013
这不是一个好的解决方案。您必须在 中包含每个特殊的正则表达式字符,这可能会变得很困难。vals
0赞 Dason 2/13/2013
@RyanThompson 当然 - 但这是一个开始。而且特殊字符的列表是有限的,所以这不是一个非常巨大的负担。我并不是说这是一个最佳解决方案——只是说这是一种可能性。另请注意,您的方法可能会对通常不被视为正则表达式字符的字符进行转义,因此也可能被视为“坏”。
1赞 Ryan C. Thompson 2/13/2013
我的方法可能会转义一些不需要转义的字符,但这样做不会有什么坏处,因为对于 PCRE,任何非字母数字字符在以反斜杠为前缀时都被视为文字,即使不需要反斜杠。
0赞 Ken Williams 9/2/2016
这种方法的另一个致命缺陷是它连续应用其转义,而不是一次全部应用,因此在一次传递中所做的更改可能会在下一次传递时出现乱码。
2赞 Ken Williams 9/3/2016
你是对的,我认为它按预期工作。我没有仔细观察,没有注意到反斜杠是列表中的第一个替换,并且由于反斜杠也是 添加的唯一字符,因此您永远不会插入字符然后对插入执行操作。gsub()
32赞 Ryan C. Thompson 2/13/2013 #2

我编写了 Perl 函数的 R 版本:quotemeta

library(stringr)
quotemeta <- function(string) {
  str_replace_all(string, "(\\W)", "\\\\\\1")
}

我总是使用正则表达式的perl风格,所以这对我有用。我不知道它是否适用于 R 中的“正常”正则表达式。

编辑:我找到了解释为什么这样做的来源。它位于 perlre 手册页的 Quoting Metacharacters 部分

这曾经用于一个常见的成语中,用于禁用或引用要用于模式的字符串中正则表达式元字符的特殊含义。只需引用所有非“单词”字符:

$pattern =~ s/(\W)/\\$1/g;

正如你所看到的,上面的R代码是这个相同的替换的直接翻译(在经历了反斜杠地狱之后)。手册页还说(强调我的):

与其他一些正则表达式语言不同,没有非字母数字的反斜杠符号。

这强化了我的观点,即该解决方案仅保证用于PCRE。

评论

0赞 patL 3/21/2022
Ryan,我可能不太了解您的函数的正确用法,但是当我尝试删除空格的正则表达式时,它失败了:。我该如何管理它?quotemeta('\s+')
6赞 Paul Lemmens 4/23/2019 #3

比函数更简单的方法是@ryanthompson字符串前面加上后缀。请参阅帮助文件。\\Q\\E?base::regex

2赞 Ryan C. Thompson 5/6/2021 #4

使用 rex

这些天来,我用 编写所有正则表达式。对于您的特定示例,完全按照您的要求执行操作:rexrex

library(rex)
library(assertthat)
x = "foo[bar]"
y = rex(x)
assert_that(y == "foo\\[bar\\]")

但当然,所做的远不止于此。这个问题提到了构建正则表达式,而这正是设计的目的。例如,假设我们想匹配 中的确切字符串,之前或之后都没有:rexrexx

x = "foo[bar]"
y = rex(start, x, end)

现在 y 是并且只会匹配 x 中包含的确切字符串。^foo\[bar\]$

1赞 antonio 2/10/2022 #5

根据:?regex

该符号与“word”字符(、扩展的同义词)匹配,并且是其否定 ()。\w[[:alnum:]_]\W[^[:alnum:]_]

因此,使用捕获组,我们可以检测非单词字符的出现,并使用 -syntax 对其进行转义:(\\W)\\1

> gsub("(\\W)", "\\\\\\1", "[](){}.|^+$*?\\These are words")
[1] "\\[\\]\\(\\)\\{\\}\\.\\|\\^\\+\\$\\*\\?\\\\These\\ are\\ words"

或者类似地,将 ."([^[:alnum:]_])""(\\W)"