- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当使用像gsub
和grep
这样的基本R字符串函数时,习惯上总是指定perl = TRUE
有什么不利之处吗?这有什么缺点吗?
使用perl=TRUE
,表达式可以做更多的事情(例如,您可以使用前瞻性声明或后置声明,或者可以使用\\U
进行大小写转换),并且性能也更快,如文档所述。
那么,还有什么缺点吗? perl = TRUE
是否不是仅用于向后兼容的默认设置?当perl = TRUE时,我应该注意可移植性问题吗?
最佳答案
比较苹果和橙子不是一个好主意,因为PCRE regex的作用远不如TRE regex烯酸。尽管它们具有相似的结构,但即使如此,外表还是可能是欺骗性的。
TRE和PCRE有何相似之处
TRE支持将文字作为PCRE。文字是普通字符,8位十六进制字符(例如\x1B
),宽十六进制字符(例如\x{263a}
)或转义字符:\a
,\e
,\f
,< cc>,\n
,\r
。 PCRE supports more:\t
(“ control-x”,其中\cx
是任何ASCII字符),x
(八进制代码\0dd
的字符),0dd
(八进制代码\ddd
的字符或反向引用),ddd
(八进制代码为\o{ddd..}
的字符),ddd..
(十六进制代码为\xhh
的字符),hh
(十六进制代码为\x{hhh..}
的字符)。
两者都有一个hhh..
wildcard,但是在TRE中,它与任何char匹配,在PCRE中,它仅与任何char匹配,但与换行符不符(哪些依赖于换行符PCRE动词.
,(*CR)
,(*LF)
,(*CRLF)
,(*ANYCRLF)
)。 (*ANY)
将产生gsub(".+", "~", "_\n_")
,但是~
将产生gsub(".+", "~", "_\n_", perl=TRUE)
。另一个相反的示例,要使TRE ~\n~
在PCRE中起作用,请使用.
修饰符,使用(?n)
产生gsub("(?n).+", "~", "_\n_")
(无法在行尾样式之间进行选择)。在PCRE模式中,要使~\n~
与换行符匹配,您需要在.
之前使用(?s)
内联DOTALL修饰符(或类似修饰符组的.
)。
两者都支持alternation operator,但是由于TRE是text-directed engine最长的替代匹配,而在PCRE中,最左边的替代“获胜”。 (?s:.*)
产生sub("(s|su)", "~", "sub")
(因为~b
是最长的匹配替代方案),但是su
产生sub("(s|su)", "~", "sub", perl=TRUE)
(因为~ub
是匹配的第一个替代方案)。
两者都支持backreferences,但是TRE仅支持多达9个反向引用。如果需要10个或更多,请使用PCRE。 s
将找到一个匹配项,没有sub("(.)\\1(.)\\2(.)\\3(.)\\4(.)\\5(.)\\6(.)\\7(.)\\8(.)\\9(.)\\10", "~", "112233445566778899aa", perl=TRUE)
,则不会检测到任何匹配项。
两者似乎都具有类似character classes,perl=TRUE
的构造,但实际上,在TRE所属的POSIX世界中,这些被称为方括号表达式。尽管您可以在两个字符范围中都定义文字字符范围,或在它们之间具有OR关系来指定文字字符,但您不能在方括号表达式中使用shorthand char classes,也不能使用任何转义序列。 TRE正则表达式中的[...]
模式被视为1个或多个反斜杠或/和[\d]+
字母,而在PCRE模式中,它将被解析为1个以上的数字(尝试d
(-> gsub("[\\d]+", "~", "00\\99d")
)和00~99~
(-> gsub("[\\d]+", "~", "00\\99d", perl=TRUE)
))。这个事实将解释为什么PCRE模式中的~\~d
匹配1+ [\]\-\[]+
,]
或-
,而不是在需要使用“智能放置”(如[
)的TRE表达式中。
TRE和PCRE支持[][-]
(数字),\d
(非数字),\D
(“单词”字符),\w
(“非单词”字符),\W
(任何空格) ,\s
(任何非空白)shorthand character classes。但是,PCRE also supports \S
(任何垂直空白),\v
(除了垂直空白以外的任何字符),\V
(任何水平空白),\h
(不是水平空白的任何字符), \H
(任何非换行符),\N
(任何Unicode字素,在处理带变音符号的字母时很有用),\X
(任何Unicode换行序列)。
两种口味都支持quantifiers,常规,贪婪\R
,?
,*
,惰性+
,??
,*?
,范围/限制量词,例如贪婪+?
,{3}
或< cc>及其懒惰的对象,后面是{8,26}
。请注意,TRE对限制量词的支持较差(仅用于supports values lower than 256 for {3,}
quantifier,并且对于?
和更大的值会抛出“内存不足”异常。请确保始终将{min}
值用作最小值)您暗示,因为{2557,}
in TRE actually matches 3 occurrences。但是,PCRE支持possessive quantifiers,0
,{,2}
,++
,?+
。用它们量化的模式不允许回溯到它们,一旦匹配,引擎就不会重试它们此外,就像所有其他基于Henry Spencer的可追溯到1986年的regex库的regex库(Tcl,PostgreSQL)一样,应避免在regex中将懒惰的量词和贪婪的量词混合在同一级别上,因为the first pattern sets the greediness of the whole pattern level并经常导致意外的结果。
两种口味均支持POSIX character classes,可在*+
... {1,5}+
之间使用。但是,TRE支持[
(字母数字),]
(字母),[:alnum:]
(水平空格),[:alpha:]
(控制字符),[:blank:]
(数字),[:cntrl:]
(可见字符),空格和控制字符),[:digit:]
(小写字母),[:graph:]
(所有可打印字符),[:lower:]
(符号和标点符号),[:print:]
(任何空格),[:punct:]
(大写字母)和
[:space:]
(“单词”字符)和
[:upper:]
(任何ASCII字符)。
两者都支持单词边界,但是PCRE模式以更可靠的方式做到这一点。 cf.
[:xdigit:]
产生
[:word:]
,
[:ascii:]
产生
gsub("\\b", "~", "CODE")
。尽管TRE支持特定的前
~C~O~D~E~
和后
gsub("\\b", "~", "CODE", perl=T)
字边界,但PCRE
~CODE~
仍然更可靠。
两者都支持内联
modifiers,当在模式中使用它们时,它们会更改某些模式行为,例如
\<
。 TRE支持
\>
(不区分大小写),
\b
(点不再与换行符匹配),
(?i)
(使正则表达式以右关联方式而不是正常的左关联方式进行匹配。默认情况下,串联为左按照Std 1003.1-2001(POSIX)
base specifications on regular expressions中给出的语法在TRE中进行关联。更改整个正则表达式匹配的内容)和
i
(交换贪婪,
n
变得贪婪,
r
变得懒惰)。 PCRE支持
U
和
*?
修饰符,以及更多:
*
(
i
和
U
匹配行的开头/结尾,而不是整个字符串),
m
(点与换行符匹配),
^
(允许使用名称捕获具有相同名称的组),
$
(如果该组合不是有效的正则表达式标记,则使带有反斜杠的字母转义为错误) ),
s
(使
x
仅匹配字符串的最末尾,否则,它也匹配字符串中最后尾随换行符之前的位置)和
J
(仅匹配字符串的开头,就好像前面是
X
或
D
)。
回溯方面
请参见
TRE docs:TRE中使用的匹配算法在要搜索的文本长度中使用线性最坏情况时间,并在所用正则表达式的长度中使用二次最坏情况时间。换句话说,该算法的时间复杂度为O(M2N),其中M为正则表达式的长度,N为文本的长度。这会导致类似
$
的模式搜索重复的连续子字符串的问题。请参见
Remove repeated elements in a string with R。
因此,当您需要大量依赖回溯时,请选择PCRE。
PCRE可以做什么,TRE不能做什么
TRE最明显的缺点是它不支持环视。但是,有
a lot of things that PCRE can boast of:
A
PCRE verb combination在匹配时匹配和跳过模式
Recursion to match whole patterns that can be nested
Subroutines to match nested, balanced substrings匹配递归结构
\A
anchor that matches start of string or the end of the previous successful match
^
branch reset group允许捕获其中的组共享相同的ID
(.{2,})\1+
and opposite (*SKIP)(*FAIL)
Unicode character properties
Case-changing operators in the replacement patterns turning the whole or part of the match to lower (\G
) or upper case ((?|...|...)
) (up to the \p{...}
or end of match if it is missing)(实际上,它是R中使用的PCRE库的扩展)
无限宽正向后方替代项
\P{...}
match reset operator(
\L
reference)
PCRE支持命名捕获组,但是在R.
Here is a custom example中并未广泛使用它们。
还有更多内容,例如
anchors(
\U
(字符串的开头),
\E
(字符串的结尾),
\K
(字符串的最结尾)),
conditional "if-then-else" construct,
atomic groupings(在与所有格量词相同,但不允许回溯到整个模式序列中,等等。
Windows 7,Linux Ubuntu 16.04,MacOS Sierra 10.12.6中的基准测试
如果要比较R中的TRE和PCRE regex引擎的性能,则应使用简单的模式,将这两个引擎的文字实际匹配。
我主要在Windows中使用R,但是我专门为此测试在Linux VM上安装了R 3.2.3。 MacOS的结果是从
t.kalinowski's answer借用的。
让我们使用微基准库比较TRE(默认)和PCRE(
\K
)regex性能(请参阅更多的
benchmarking options in R):
library(microbenchmark)
txt <- "Butterflies are insects in the macrolepidopteran clade Rhopalocera from the order Lepidoptera, which also includes moths. Adult butterflies have large, often brightly coloured wings, and conspicuous, fluttering flight. The group comprises the large superfamily Papilionoidea, which contains at least one former group, the skippers (formerly the superfamily \"Hesperioidea\") and the most recent analyses suggest it also contains the moth-butterflies (formerly the superfamily \"Hedyloidea\"). Butterfly fossils date to the Paleocene, which was about 56 million years ago."
\A
提取括号中的最后一个文本,这是R中非常常见的
\Z
操作:
# sub('.*\\((.*)\\).*', '\\1', txt)
# => [1] "formerly the superfamily \"Hedyloidea\""
PCRE_1 <- function(text) { return(sub('.*\\((.*)\\).*', '\\1', txt, perl=TRUE)) }
TRE_1 <- function(text) { return(sub('.*\\((.*)\\).*', '\\1', txt)) }
test <- microbenchmark( PCRE_1(txt), TRE_1(txt), times = 500000 )
test
WINDOWS
-------
Unit: microseconds
expr min lq mean median uq max neval
PCRE_1(txt) 163.607 165.418 168.65393 166.625 167.229 7314.588 5e+05
TRE_1(txt) 70.031 72.446 74.53842 73.050 74.257 38026.680 5e+05
MacOS
-----
Unit: microseconds
expr min lq mean median uq max neval
PCRE_1(txt) 31.693 32.857 37.00757 33.413 35.805 43810.177 5e+05
TRE_1(txt) 46.037 47.199 53.06407 47.807 51.981 7702.869 5e+05
Linux
------
Unit: microseconds
expr min lq mean median uq max neval
PCRE_1(txt) 10.557 11.555 13.78216 12.097 12.662 4301.178 5e+05
TRE_1(txt) 25.875 27.350 31.51925 27.805 28.737 17974.716 5e+05
\z
仅在Windows中获胜,速度是其两倍以上。在MacOS和Linux上,PCRE(
perl=TRUE
)版本以相似的比率获胜。
# regmatches(txt, gregexpr("\"[A-Za-z]+\"", txt))
# => [1] "\"Hesperioidea\"" "\"Hedyloidea\""
PCRE_2 <- function(text) { return(regmatches(txt, gregexpr("\"[A-Za-z]+\"", txt, perl=TRUE))) }
TRE_2 <- function(text) { return(regmatches(txt, gregexpr("\"[A-Za-z]+\"", txt))) }
test <- microbenchmark( PCRE_2(txt), TRE_2(txt), times = 500000 )
test
WINDOWS
-------
Unit: microseconds
expr min lq mean median uq max neval
PCRE_2(txt) 324.799 330.232 349.0281 332.646 336.269 124404.14 5e+05
TRE_2(txt) 187.755 191.981 204.7663 193.792 196.208 74554.94 5e+05
MacOS
-----
Unit: microseconds
expr min lq mean median uq max neval
PCRE_2(txt) 63.801 68.115 75.51773 69.164 71.219 47686.40 5e+05
TRE_2(txt) 63.825 67.849 75.20246 68.883 70.933 49691.92 5e+05
LINUX
-----
Unit: microseconds
expr min lq mean median uq max neval
PCRE_2(txt) 30.199 34.750 44.05169 36.151 43.403 38428.2 5e+05
TRE_2(txt) 37.752 41.854 52.58230 43.409 51.781 38915.7 5e+05
关于r - R中的正则表达式:'perl = TRUE'与默认值(PCRE与TRE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47240375/
我正在从 Stata 迁移到 R(plm 包),以便进行面板模型计量经济学。在 Stata 中,面板模型(例如随机效应)通常报告组内、组间和整体 R 平方。 I have found plm 随机效应
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
我想要求用户输入整数值列表。用户可以输入单个值或一组多个值,如 1 2 3(spcae 或逗号分隔)然后使用输入的数据进行进一步计算。 我正在使用下面的代码 EXP <- as.integer(rea
当 R 使用分类变量执行回归时,它实际上是虚拟编码。也就是说,省略了一个级别作为基础或引用,并且回归公式包括所有其他级别的虚拟变量。但是,R 选择了哪一个作为引用,以及我如何影响这个选择? 具有四个级
这个问题基本上是我之前问过的问题的延伸:How to only print (adjusted) R-squared of regression model? 我想建立一个线性回归模型来预测具有 15
我在一台安装了多个软件包的 Linux 计算机上安装了 R。现在我正在另一台 Linux 计算机上设置 R。从他们的存储库安装 R 很容易,但我将不得不使用 安装许多包 install.package
我正在阅读 Hadley 的高级 R 编程,当它讨论字符的内存大小时,它说: R has a global string pool. This means that each unique strin
我们可以将 Shiny 代码写在两个单独的文件中,"ui.R"和 "server.R" , 或者我们可以将两个模块写入一个文件 "app.R"并调用函数shinyApp() 这两种方法中的任何一种在性
我正在使用 R 通过 RGP 包进行遗传编程。环境创造了解决问题的功能。我想将这些函数保存在它们自己的 .R 源文件中。我这辈子都想不通怎么办。我尝试过的一种方法是: bf_str = print(b
假设我创建了一个函数“function.r”,在编辑该函数后我必须通过 source('function.r') 重新加载到我的全局环境中。无论如何,每次我进行编辑时,我是否可以避免将其重新加载到我的
例如,test.R 是一个单行文件: $ cat test.R # print('Hello, world!') 我们可以通过Rscript test.R 或R CMD BATCH test.R 来
我知道我可以使用 Rmd 来构建包插图,但想知道是否可以更具体地使用 R Notebooks 来制作包插图。如果是这样,我需要将 R Notebooks 编写为包小插图有什么不同吗?我正在使用最新版本
我正在考虑使用 R 包的共享库进行 R 的站点安装。 多台计算机将访问该库,以便每个人共享相同的设置。 问题是我注意到有时您无法更新包,因为另一个 R 实例正在锁定库。我不能要求每个人都关闭它的 R
我知道如何从命令行启动 R 并执行表达式(例如, R -e 'print("hello")' )或从文件中获取输入(例如, R -f filename.r )。但是,在这两种情况下,R 都会运行文件中
我正在尝试使我当前的项目可重现,因此我正在创建一个主文档(最终是一个 .rmd 文件),用于调用和执行其他几个文档。这样我自己和其他调查员只需要打开和运行一个文件。 当前设置分为三层:主文件、2 个读
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
我的 R 包中有以下描述文件 Package: blah Title: What the Package Does (one line, title case) Version: 0.0.0.9000
有没有办法更有效地编写以下语句?accel 是一个数据框。 accel[[2]]<- accel[[2]]-weighted.mean(accel[[2]]) accel[[3]]<- accel[[
例如,在尝试安装 R 包时 curl作为 usethis 的依赖项: * installing *source* package ‘curl’ ... ** package ‘curl’ succes
我想将一些软件作为一个包共享,但我的一些脚本似乎并不能很自然地作为函数运行。例如,考虑以下代码块,其中“raw.df”是一个包含离散和连续类型变量的数据框。函数“count.unique”和“squa
我是一名优秀的程序员,十分优秀!