提问人:Richie Cotton 提问时间:12/31/2014 最后编辑:k-dubsRichie Cotton 更新时间:6/15/2023 访问量:179741
如何处理像 \^$ 这样的特殊字符?*|+()[{ 在我的正则表达式中?
How do I deal with special characters like \^$.?*|+()[{ in my regex?
问:
我想匹配正则表达式特殊字符 .我试过了:\^$.?*|+()[{
x <- "a[b"
grepl("[", x)
## Error: invalid regular expression '[', reason 'Missing ']''
(等效或。stringr::str_detect(x, "[")
stringi::stri_detect_regex(x, "[")
将值加倍以转义它不起作用:
grepl("[[", x)
## Error: invalid regular expression '[[', reason 'Missing ']''
使用反斜杠也是如此:
grepl("\[", x)
## Error: '\[' is an unrecognized escape in character string starting ""\["
如何匹配特殊字符?
在一些特殊情况下,这些问题已经足够古老且写得很好,以至于可以厚颜无耻地将其作为副本关闭:
R 正则表达式
中的转义句点 如何在 R 中转义问号?
正则表达式中的转义管道 (“|”)
答:
使用双反斜杠进行转义
R 将反斜杠视为字符常量的转义值。(...正则表达式也是如此。因此,在为模式提供字符参数时需要两个反斜杠。第一个实际上不是一个角色,而是它使第二个变成了一个角色。您可以看到如何使用 cat
处理它们。
y <- "double quote: \", tab: \t, newline: \n, unicode point: \u20AC"
print(y)
## [1] "double quote: \", tab: \t, newline: \n, unicode point: €"
cat(y)
## double quote: ", tab: , newline:
## , unicode point: €
延伸阅读:在 R 中用反斜杠转义反斜杠会在字符串中产生 2 个反斜杠,而不是 1 个
要在正则表达式中使用特殊字符,最简单的方法通常是使用反斜杠对它们进行转义,但如上所述,反斜杠本身需要转义。
grepl("\\[", "a[b")
## [1] TRUE
要匹配反斜杠,您需要双重转义,从而产生四个反斜杠。
grepl("\\\\", c("a\\b", "a\nb"))
## [1] TRUE FALSE
该软件包包含每个特殊字符的常量,以避免键入错误的斜杠。rebus
library(rebus)
OPEN_BRACKET
## [1] "\\["
BACKSLASH
## [1] "\\\\"
有关更多示例,请参阅:
?SpecialCharacters
您的问题可以通过以下方式解决:
library(rebus)
grepl(OPEN_BRACKET, "a[b")
形成字符类
grepl("[?]", "a?b")
## [1] TRUE
其中两个特殊字符在字符类中具有特殊含义:和 。\
^
反斜杠仍然需要转义,即使它位于字符类中。
grepl("[\\\\]", c("a\\b", "a\nb"))
## [1] TRUE FALSE
插入符号只有在左方括号的正后方括号之后时才需要转义。
grepl("[ ^]", "a^b") # matches spaces as well.
## [1] TRUE
grepl("[\\^]", "a^b")
## [1] TRUE
rebus
还允许您形成字符类。
char_class("?")
## <regex> [?]
使用预先存在的字符类
如果要匹配所有标点符号,可以使用字符类。[:punct:]
grepl("[[:punct:]]", c("//", "[", "(", "{", "?", "^", "$"))
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
stringi
将其映射到 Unicode General Category 的标点符号,因此其行为略有不同。
stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "[[:punct:]]")
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE
您还可以使用跨平台语法来访问 UGC。
stri_detect_regex(c("//", "[", "(", "{", "?", "^", "$"), "\\p{P}")
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE
使用 \Q \E 转义符
将字符放在 和 之间会使正则表达式引擎从字面上而不是将其视为正则表达式。\\Q
\\E
grepl("\\Q.\\E", "a.b")
## [1] TRUE
rebus
允许您编写正则表达式的文本块。
literal(".")
## <regex> \Q.\E
不要使用正则表达式
正则表达式并不总是答案。如果你想匹配一个固定的字符串,那么你可以这样做,例如:
grepl("[", "a[b", fixed = TRUE)
stringr::str_detect("a[b", fixed("["))
stringi::stri_detect_fixed("a[b", "[")
评论
cat
\\Q
\\E
?base::regex
stringr::str_detect("a[b", fixed("["))
我认为匹配角色的最简单方法,例如
\^$.?*|+()[
使用 R 中的字符类。 请考虑以下操作来清除数据文件中的列标题,其中可能包含空格和标点符号:
> library(stringr)
> colnames(order_table) <- str_replace_all(colnames(order_table),"[:punct:]|[:space:]","")
这种方法允许我们字符串字符类以匹配标点字符,以及空格字符,通常必须进行转义才能检测到。您可以在下面的备忘单中了解有关字符类的更多信息,也可以输入以查看有关此内容的更多信息。\\
?regexp
https://www.rstudio.com/wp-content/uploads/2016/09/RegExCheatsheet.pdf
如果向量的值包含特殊的正则表达式元字符,并且需要从向量创建替代,则需要使用
regex.escape <- function(string) {
gsub("([][{}()+*^${|\\\\?.])", "\\\\\\1", string)
}
x <- c("a[b", "c++", "d()e")
regex <- paste(regex.escape(x), collapse="|")
## => a\[b|c\+\+|d\(\)e
请注意 - 如果你使用像 ///等这样的提取基本 R 正则表达式方法 - TRE 正则表达式风格,作为一个 POSIX 正则表达式引擎,总是返回最长的匹配项(即检查所有备选项并返回最长的匹配项)。regmatches
gregexpr
regexec
如果您使用带有 perl=TRUE
的基本 R 正则表达式函数或 stringr
/stringi
ICU 正则表达式函数,则应阅读下面的摘要。
请注意,如果您构建的正则表达式没有侧面,您很可能还希望首先按长度降序对值进行排序,因为正则表达式引擎从左到右搜索匹配项,而用户定义的列表往往包含可能在字符串内相同位置匹配的项目(=向量中的值可能以相同的字符开头), 并且可能会丢失更长的匹配项,请参阅记住正则表达式引擎是渴望的):
sort.by.length.desc <- function (v) v[order( -nchar(v)) ]
所以,如果你有,你可以只使用x <- c("a[b", "c++", "d()e", "d()ee")
x <- c("a[b", "c++", "d()e", "d()ee")
regex <- paste(regex.escape(sort.by.length.desc(x)), collapse="|")
# => d\(\)ee|d\(\)e|a\[b|c\+\+
请注意前面的 。d\(\)ee
\d\(\)e
在较长正则表达式的中间/开始/结尾使用一组备选方案
您需要使用任何类型的组对备选方案进行分组,如果不需要访问组值,则不捕获组,如果需要访问值,则需要捕获组。使用明确单词边界的示例:
x <- c("a[b", "c++", "d()e", "d()ee")
text <- "aaaa[b,abc++,d()e,d()ee"
regex <- paste0("(?!\\B\\w)(?:", paste(regex.escape(sort.by.length.desc(x)), collapse="|"), ")(?<!\\w\\B)")
## -> (?!\B\w)(?:d\(\)ee|d\(\)e|a\[b|c\+\+)(?<!\w\B)
unlist(regmatches(text,gregexpr(regex, text, perl=TRUE)))
## => [1] "d()e" "d()ee"
您可以注意到,该模式现在看起来像 + 您的交替 + ,其中交替被放入一个非捕获组 () 中,如果下一个字符是单词字符,则需要单词边界,如果紧挨着左侧的字符是单词字符,则该部分需要单词边界。(?!\B\w)(?:
)(?<!\w\B)
(?:d\(\)ee|d\(\)e|a\[b|c\+\+)
(?!\B\w)
(?<!\w\B)
评论