PCRE正则表达式语法

时间:2012-06-04 20:17:28

标签: regex pcre

我想这或多或少是一个由两部分组成的问题,但这里首先是基础知识:我正在编写一些PHP来使用preg_match_all查找变量以查找由}}结尾的字符串。然后迭代返回的每个字符串,用MySQL查询中的数据替换它找到的字符串。

第一个问题是:有什么好的网站可以真正了解PCRE表达的细节吗?我在Google上做了很多搜索,但到目前为止我能找到的最好的是http://www.regular-expressions.info/。在我看来,那里的信息没有很好的组织,因为我不想在我需要编写复杂的正则表达式时不得不寻求帮助,请指点几个站点(或几本书!)这将有助于我将来不必打扰你们。

第二个问题是:我有这个正则表达式

"/{.*(_){1}(.*(_){1}[a-z]{1}|.*)}/"

我需要它来捕获{first_name}, {last_name}, {email}等实例。这个正则表达式有三个问题。

首先,它将“{first_name} {last_name}”视为一个字符串,它应该将其视为两个字符串。我已经能够通过检查空间的存在来解决这个问题,然后在空间上爆炸。凌乱,但它确实有效。

第二个问题是它包含标点符号作为捕获字符串的一部分。因此,如果您有“{first_name} {last_name}”,那么它会将逗号作为字符串的一部分返回。我已经能够通过简单地使用preg_replace删除句点,逗号和分号来部分解决这个问题。虽然它适用于那些标点符号项,但我的逻辑无法处理感叹号,问号和其他所有内容。

我对此正则表达式的第三个问题是它根本没有看到{email}的实例。

现在,如果你能够,愿意,并且有时间简单地将解决方案交给我这个问题,谢谢你,因为这将解决我当前的问题。但是,即使您可以这样做,请提供lmgfty,提供良好的网站作为参考和/或一本或两本书,以提供有关该主题的良好教育。由于资金紧张,网站会更受欢迎,但如果一本书是解决方案,我会找到钱(假设我的本地图书馆系统无法获得所述数量)。

3 个答案:

答案 0 :(得分:4)

当时我发现PHP自己的PCRE语法参考非常好:http://uk.php.net/manual/en/reference.pcre.pattern.syntax.php

让我们来谈谈你的表达。它比必要的冗长得多;我们将在完成此操作时简化它。

查看您要匹配的内容的一种相当简单的方法:“找到{,然后找到任意数量的字母或下划线,然后找到}”。正则表达式是(在PHP的字符串-y语法中):'/\{[a-z_]+\}/'

这将匹配您的所有示例,但也会匹配一些像{__a_b}这样的更狂野的示例。如果这不是一个选项,我们可以使用更复杂的描述:“找到一个{,然后是一堆字母,然后(尽可能经常)一个下划线后跟一堆字母,然后是{ {1}}”。在正则表达式中:}

第二个可能需要更多解释。由于我们想要重复匹配/\{([a-z]+(_[a-z]+)*\}/段的事物,我们需要将它放在括号中。然后我们说:尝试尽可能经常地找到它,但如果你根本找不到它(这就是_foo的含义)也没关系。

所以现在我们有一些东西要比较你的尝试,让我们来看看导致你问题的原因:

  • 您的表达式会匹配*中的所有字符,包括{}}以及其他一些内容。换句话说,您的正则表达式会接受{{abcde{_fgh}也是如此。
  • 您在第一个{abcde} fg_h {ijkl}之后就有了强制性_.*(这意味着与(_){1}完全相同)说:无论发生什么,如果不在这里就会爆炸!很明显,你实际上并不想这样,因为它永远不会匹配_

以下是您正则表达式匹配的简明语言的完整描述:

  1. 匹配{email}
  2. 匹配{
  3. 绝对匹配任何内容,只要您可以在此之后匹配所有剩余规则。
  4. 匹配_
  5. 匹配一个字母。
  6. 而不是那个_和单个字母,绝对一切都没问题。
  7. 匹配_
  8. 这可能与你想要的相差甚远。不过不用担心。正则表达式需要一段时间才能习惯。我认为如果你从指令的角度来考虑它是非常有帮助的,即在构建正则表达式时,尝试在头脑中构建它作为“找到它,然后找到它”等等。然后找出正确的语法来实现确切地说。

    这很难,主要是因为你头脑中没有提到的所有说明都很容易转化为正则表达式......但这就是经验的来源。我保证你会把它记下来。时间......如果你最初有条理地制作正则表达式。

    祝你好运! :)

答案 1 :(得分:1)

对于PCRE,我只是简单地消化了PCRE的联机帮助页,但是无论如何我的大脑都是那样工作......

至于匹配分隔的东西,你通常有两种方法:

  1. 匹配第一个分隔符,匹配不是结束分隔符的任何内容,匹配结束分隔符。
  2. 匹配第一个分隔符,匹配任何 ungreedily ,匹配结束分隔符。
  3. E.g。对于你的情况:

    1. \{([^}]+)\}
    2. \{(.+?)\} - 请注意 +
    3. 后的

      我在您可能想要提取的内容周围添加了一个小组。

      另请注意,特别是在#1的情况下,对于#2,如果“点匹配任何东西”生效(dotall,单行或任何您最喜欢的正则表达式调用它),它们也会匹配 - 中的换行符 - 如果这是一个问题,您需要手动排除那些以及您不想要的任何其他内容;如果您想要更像白名单的方法,请参阅上面的答案。

答案 2 :(得分:0)

  1. 这里是good regex site
  2. 这是一个可行的PCRE正则表达式:\{\w+\}
  3. 以下是它的工作原理: 它基本上是{,然后是one ore more word characters,后跟}。有趣的是,字符类实际上也包括下划线。 \w基本上是[A-Za-z0-9_]

    的简写

    所以它基本上会匹配大括号内的这些字符的任意组合,因为加号只会匹配非空的大括号。