与具有量化替代方案的较短正则表达式表示法相比,展开循环有什么优势?

2023-12-29

要求:两个表达式,exp1 and exp2,我们需要匹配两者中的一个或多个。所以我想出了,

(exp1 | exp2)*

但是在某些地方,我看到使用了以下内容,

(exp1 * (exp2 exp1*)*)

两者有什么区别?你什么时候会使用其中一种而不是另一种?

希望有一个fiddle https://jsfiddle.net/anoopelias/aj9g1w7c/将使这一点更加清楚,

var regex1 = /^"([\x00-!#-[\]-\x7f]|\\")*"$/;
var regex2 = /^"([\x00-!#-[\]-\x7f]*(\\"[\x00-!#-[\]-\x7f]*)*)"$/;

var str = '"foo \\"bar\\" baz"';
var r1 = regex1.exec(str);
var r2 = regex2.exec(str);

EDIT:当我们捕获组时,两种方法之间的行为似乎存在差异。第二种方法捕获整个字符串,而第一种方法仅捕获最后一个匹配组。查看更新fiddle https://jsfiddle.net/aj9g1w7c/1/.


两种模式的区别在于潜在的效率。

The (exp1 | exp2)*Pattern 包含一个自动禁用某些内部正则表达式匹配优化的替代。此外,此正则表达式尝试匹配字符串中每个位置的模式。

The (exp1 * (exp2 exp1*)*)表达式是按照.到展开循环 http://www.softec.lu/site/RegularExpressions/UnrollingTheLoop原则:

该优化技术用于优化表单的重复交替(expr1|expr2|...)*。这些表达式并不罕见,并且在交替中使用另一个重复也可能导致超线性匹配。超线性匹配源自undertermistic表达式(a*)*.

展开循环技术基于这样的假设:在大多数情况下,您通过重复的交替知道哪种情况应该是最常见的,哪种情况是例外的。我们将第一个称为正常情况,第二个称为特殊情况。展开循环技术的一般语法可以写为:

normal* ( special normal* )*

So, the exp1在你的例子中是normal那部分是最常见的, and exp2预计频率会降低。在这种情况下,展开模式的效率实际上比其他正则表达式高得多,因为normal*部分将抓取整个输入块,无需停止和检查each地点。

我们看一个简单的"([^"\\]|\\.)*"正则表达式测试"some text here" https://regex101.com/r/zH1mR0/1:涉及 35 个步骤:

将其展开为"[^"\\]*(\\.[^"\\]*)*" https://regex101.com/r/zH1mR0/2由于回溯少得多,因此增加了 6 个步骤。

NOTEregex101.com 的步骤数并不直接意味着一个正则表达式比另一个更有效,但是,调试表显示了回溯发生的位置,以及回溯is资源消耗。

然后我们用 JS benchmark.js 来测试模式效率:

var suite = new Benchmark.Suite();
Benchmark = window.Benchmark;
suite
  .add('Regular RegExp test', function() {
      '"some text here"'.match(/"([^"\\]|\\.)*"/);
    })
  .add('Unrolled RegExp test', function() {
      '"some text here"'.match(/"[^"\\]*(\\.[^"\\]*)*"/);
    })
  .on('cycle', function(event) {
    console.log(String(event.target));
  })
  .on('complete', function() {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  })
  .run({ 'async': true });
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.1/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/2.1.0/benchmark.js"></script>

Results:

Regular RegExp test x 9,295,393 ops/sec ±0.69% (64 runs sampled)
Unrolled RegExp test x 12,176,227 ops/sec ±1.17% (64 runs sampled)
Fastest is Unrolled RegExp test

另外,自从展开循环概念不是特定于语言的,这里有一个在线PHP测试 https://ideone.com/JaQQlA(常规模式产生~0.45,并展开一个屈服~0.22结果)。

另请参阅展开循环,何时使用 https://stackoverflow.com/questions/38018210/unroll-loop-when-to-use/38018490#38018490.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

与具有量化替代方案的较短正则表达式表示法相比,展开循环有什么优势? 的相关文章

随机推荐

  • 在某个位置插入列表的成本/复杂性是多少?

    在 Python 中 一个list https docs python org 2 tutorial datastructures html more on lists has list insert i x 到 在给定位置插入项目 在C
  • 带 .htaccess 的 PHP 根目录

    我使用的是 000webhost 它使用根文件夹中的 public html 文件夹作为站点的可见根 在该文件夹中 我有一个包含一些 PHP 脚本的资产文件夹 以及包含 PHP 索引页的其他文件夹 使用require assets incl
  • 在 F# 中运行 ML.Net Iris 演示时,我使用 TextLoader 是否错误?

    我是 F NET 新手 我正在尝试运行接受的答案中提供的 F 示例如何将介绍性 ML Net 演示转换为 F https stackoverflow com questions 50322653 how to translate the i
  • PHP无会话用户认证教程

    我需要为计算机安全项目的一部分构建自己的系统 而不使用 php 会话 仅 cookie 但我迷路了 我发现的所有教程都使用会话 有充分的理由 所以我想知道是否有人知道自己的 php 用户身份验证教程 你基本上可以像你自己一样实现一些会话 这
  • nil:NilClass 与 simple_form 和 Mongoid 的未定义方法 `valid_options'

    我有两个模型 类别和帖子 类别 rb class Category include Mongoid Document field title type gt String has many posts autosave gt true de
  • Angular 2 - 样式组件的选择器边框 css 属性

    Update 在我下面的评论中 您可以在 Google Drive 上找到一个压缩项目 任何人都可以制作一个 Plunker 我从未做过 需要更改什么 任何解释此更改的文章 博客 我有一个SearchComponent这延伸了BaseCom
  • 优化包含窗口函数的参数化 T-SQL 查询的执行计划

    编辑 我已经更新了示例代码并提供了完整的表和视图实现以供参考 但基本问题保持不变 我在尝试查询的数据库中有一个相当复杂的视图 当我尝试通过将 WHERE 子句硬编码为特定外键值来从视图中检索一组行时 视图会以最佳执行计划 正确使用索引等 快
  • PostgreSQL GROUP BY LOWER() 不起作用

    我正在尝试使用GROUP BY在 PostgreSQL 9 4 1 中 并没有像我希望的那样成功 有几个人 http bytes com topic postgresql answers 422112 group case insensit
  • 如何播放 WPF 声音文件资源

    我正在尝试在 WPF 应用程序中播放声音文件 目前我有以下电话 private void PlaySound string uriPath Uri uri new Uri pack application Media movepoint w
  • Makefile:修改模式规则中的词干

    我的目录中有文件名为data and helpers 我想用它们来创建目标文件result 目录结构如下 data A file1 file2 B file1 helpers file1 file2 目录结构在result与中相同data
  • Swift、Equatable 协议错误?

    我正在 Swift 中构建一个非常简单的结构 其中包含一组可选值 该结构必须符合 Equatable 协议 这是代码 struct MyTable Equatable var values Int Array count 64 repeat
  • 添加到表格时淡入表格行

    我有以下代码可将新行添加到表的末尾 row data last after some HTML rows 我想用类似的东西 fadeIn slow 所以每一行在出现之前都会淡入 但我似乎没有得到任何动画 row data last afte
  • 在Golang中画一个矩形?

    我想绘制一个带有一些矩形 条形码的邮寄标签 然后最终生成一个 PNG PDF 文件 除了使用基元 逐像素 绘制形状之外 还有更好的方法在 Go 中绘制形状吗 标准 Go 库不提供原始绘图或绘画功能 它提供的是颜色模型 image color
  • 如何从handlebarsjs访问这个json对象

    如何从handlebarsjs访问这个json对象 id 9 name Name1 address address1 city city1 state KS zip 11111 country USA fax 111111 phone 11
  • 在新订单电子邮件中显示自定义产品字段

    我在一个名为的产品中创建了一个自定义字段课程日期 我给了它一个日期 例如 1 月 30 日 这是我在电子邮件中收到的内容 但没有显示 我是否遗漏了什么 使用下面的新代码片段编辑的代码
  • 在此 Visual Basic 脚本中需要帮助:以静默模式启动程序

    我正在尝试以静默模式启动程序来安装某个应用程序 以静默模式启动安装的命令行如下 setup exe s v q 我尝试使用以下内容 strCmd C setup exe s v q 但显然这是行不通的 任何人都可以帮助我编写正确的语法 我知
  • 检查目标时出错:预期dense_Dense2具有形状x,但得到形状为y的数组

    这是我在张量流中迈出的第一步 Idea 有一些数字模式 数字数组 Pattern number 以及与该模式对应的类别 从0到2的数字 Category 0 1 2 我遵循结构数据 xs Pattern ys Category 例如 xs
  • MySQL - CONCAT 两个字段并在 WHERE 子句中使用它们

    正如标题所示 我想知道如何concat一个中的两个字段where clause in mysql 这是我想要实现的目标的一个例子 SELECT CONCAT WS first name last name AS name FROM user
  • 使用 Netty 的 UDP 服务器中丢失大量 UDP 请求

    我用 Netty 编写了一个简单的 UDP 服务器 它只是在日志中打印出收到的消息 帧 为此 我创建了一个简单的帧解码器解码器和一个简单的消息处理程序 我还有一个可以顺序和 或并行发送多个请求的客户端 当我配置我的客户端测试器以顺序发送数百
  • 与具有量化替代方案的较短正则表达式表示法相比,展开循环有什么优势?

    要求 两个表达式 exp1 and exp2 我们需要匹配两者中的一个或多个 所以我想出了 exp1 exp2 但是在某些地方 我看到使用了以下内容 exp1 exp2 exp1 两者有什么区别 你什么时候会使用其中一种而不是另一种 希望有