草庐IT

PHP 正则表达式使 Apache 崩溃

coder 2023-11-10 原文

我有一个匹配模板系统的正则表达式,不幸的是,它似乎在一些适度琐碎的查找中使 apache(它在 Windows 上运行)崩溃。我已经研究了这个问题,并且有一些关于增加堆栈大小等的建议,但似乎都没有用,而且我真的不喜欢通过提高限制来处理此类问题,因为它通常只会将错误推向 future 。

关于如何更改正则表达式以使其不太可能出错的任何想法?

我的想法是捕获最里面的 block (在这种情况下 {block:test}This should be catched first!{/block:test})然后我将 str_replace 开始/结束标记并通过正则表达式重新运行整个过程,直到没有剩余的 block 。

正则表达式:

~(?P<opening>{(?P<inverse>[!])?block:(?P<name>[a-z0-9\s_-]+)})(?P<contents>(?:(?!{/?block:[0-9a-z-_]+}).)*)(?P<closing>{/block:\3})~ism

示例模板:

<div class="f_sponsors s_banners">
    <div class="s_previous">&laquo;</div>
    <div class="s_sponsors">
        <ul>
            {block:sponsors}
            <li>
                <a href="{var:url}" target="_blank">
                    <img src="image/160x126/{var:image}" alt="{var:name}" title="{var:name}" />
                </a>
            {block:test}This should be caught first!{/block:test}
            </li>
            {/block:sponsors}
        </ul>
    </div>
    <div class="s_next">&raquo;</div>
</div>

我想这是一个远景。 :(

最佳答案

试试这个:

'~(?P<opening>\{(?P<inverse>[!])?block:(?P<name>[a-z0-9\s_-]+)\})(?P<contents>[^{]*(?:\{(?!/block:(?P=name)\})[^{]*)*)(?P<closing>\{/block:(?P=name)\})~i'

或者,以可读的形式:

'~(?P<opening>
  \{
  (?P<inverse>[!])?
  block:
  (?P<name>[a-z0-9\s_-]+)
  \}
)
(?P<contents>
  [^{]*(?:\{(?!/block:(?P=name)\})[^{]*)*
)
(?P<closing>
  \{
  /block:(?P=name)
  \}
)~ix'

最重要的部分在 (?P<contents>..) 中群组:

[^{]*(?:\{(?!/block:(?P=name)\})[^{]*)*

开始时,我们唯一感兴趣的字符是左大括号,因此我们可以使用 [^{]* 来处理任何其他字符。 .只有在我们看到 { 之后我们要检查它是否是 {/block} 的开头吗?标签。如果不是,我们继续使用它并开始扫描下一个,并根据需要重复。

使用 RegexBuddy,我通过将光标放在 {block:sponsors} 的开头来测试每个正则表达式标记和调试。然后我从结束 {/block:sponsors} 中删除了结束括号标记以强制匹配失败并再次调试。您的正则表达式需要 940 步才能成功,需要 2265 步才能失败。我的成功走了 57 步,失败了 83 步。

附带说明,我删除了 s修饰符,因为因为我没有使用点( . )和 m修饰符,因为从来不需要它。我还使用了命名反向引用 (?P=name)而不是 \3根据@DaveRandom 的极好建议。我转义了所有大括号({}),因为我发现这样更容易阅读。


编辑:如果你想匹配最里面命名 block ,改变正则表达式的中间部分:

(?P<contents>
  [^{]*(?:\{(?!/block:(?P=name)\})[^{]*)*
)

...为此(正如@Kobi 在他的评论中所建议的那样):

(?P<contents>
  [^{]*(?:\{(?!/?block:[a-z0-9\s_-]+\})[^{]*)*
)

最初,(?P<opening>...) group 会捕获它看到的第一个开始标签,然后是 (?P<contents>..) group 会消费任何东西——包括其他标签——只要它们不是与 (?P<opening>...) 找到的标签相匹配的结束标签。团体。 (然后 (?P<closing>...) 组将继续使用它。)

现在,(?P<contents>...)组拒绝匹配任何 标记,无论名称是什么,开始或结束(注意开头的/?)。所以正则表达式最初开始匹配 {block:sponsors}标签,但是当它遇到 {block:test}标签,它会放弃该匹配并返回搜索开始标签。它再次从 {block:test} 开始标签,这次在找到 {/block:test} 时成功完成匹配结束标记。

这样描述听起来效率很低,但事实并非如此。我之前描述的技巧,吸食非牙套,淹没了这些错误开始的影响。你几乎在每个位置都进行了负面前瞻,现在你只在遇到 { 时才做一个。 .您甚至可以使用所有格量词,正如@godspeedlee 所建议的那样:

(?P<contents>
  [^{]*+(?:\{(?!/?block:[a-z0-9\s_-]+\})[^{]*+)*+
)

...因为您知道它永远不会消耗任何它以后必须返回的东西。这会稍微加快速度,但这并不是真正必要的。

关于PHP 正则表达式使 Apache 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11850676/

有关PHP 正则表达式使 Apache 崩溃的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  3. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  4. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  5. ruby - 正则表达式将非英文字母匹配为非单词字符 - 2

    @raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://

  6. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  7. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

  8. ruby - 正则表达式 - 排除一个字符 - 2

    这是一个例子:s="abcd+subtext@example.com"s.match(/+[^@]*/)Result=>"+subtext"问题是,我不想在其中包含“+”。我希望结果是“潜台词”,没有+ 最佳答案 您可以在正则表达式中使用括号来创建匹配组:s="abcd+subtext@example.com"s=~/\+([^@]*)/&&$1=>"subtext" 关于ruby-正则表达式-排除一个字符,我们在StackOverflow上找到一个类似的问题:

  9. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  10. Ruby 正则表达式匹配逗号,但忽略括号中的逗号 - 2

    我正在尝试通过正则表达式拆分参数列表。这是一个带有我的参数列表的字符串:"a=b,c=3,d=[1,3,5,7],e,f=g"我想要的是:["a=b","c=3","d=[1,3,5,7]","e","f=g"]我试过先行,但Ruby不允许使用动态范围后行,所以这行不通:/(?如何让正则表达式忽略方括号中的所有内容? 最佳答案 也许这样的东西对你有用:str.scan(/(?:\[.*?\]|[^,])+/)编辑再三考虑。简单的非贪婪匹配器在某些嵌套括号的情况下会失败。 关于Ruby正则

随机推荐