什么是理解其他人写的reg表达的好方法

时间:2013-02-25 20:45:31

标签: regex

我被要求修改其他人写的正则表达式。该表达式用于检查url匹配。是非常长,超过100个字符,并没有很好的文件记录。有没有什么技巧或捷径如何解决这样的问题?

看起来像这样:

/^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/

4 个答案:

答案 0 :(得分:3)

尝试使用YAPE::Regex::Explain执行此操作:

perl -MYAPE::Regex::Explain -e '
    my $regex = "/^...$/";
    print YAPE::Regex::Explain->new($regex)->explain;
'

样本输出

The regular expression:



matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  /                        '/'
----------------------------------------------------------------------
  ^                        the beginning of the string
----------------------------------------------------------------------
  (                        group and capture to \1 (optional
                           (matching the most amount possible)):
----------------------------------------------------------------------
    (                        group and capture to \2 (optional
                             (matching the most amount possible)):
----------------------------------------------------------------------
(...)

也请看这篇文章:https://stackoverflow.com/questions/772594/regular-expression-explained-with-words

答案 1 :(得分:2)

将其分成多行,并逐一计算出来。如果您不知道如何执行此操作,则需要了解更多正则表达式语法,以了解组,重复,交替和字符类的工作方式。

有一些网站可以帮助您了解这些内容是什么,例如,您可以将鼠标悬停在http://regexr.com上输入的正则表达式中,并查看该部分的突出显示和描述,或将其放入{{3}并以不同的颜色突出显示整个正则表达式。

以下是我将你的正则表达式分解为更易于处理的块的方法:

^
(
  ([\w]+:)?
  \/\/
)?
(
  (
    [\d\w]
    |
    %[a-fA-f\d]{2,2}
  )+
  (
    :
    (
      [\d\w]
      |
      %[a-fA-f\d]{2,2}
    )+
  )?
  @
)?
(
  [\d\w][-\d\w]{0,253}[\d\w]\.
)+
[\w]{2,4}
(:[\d]+)?
(
  \/
  (
    [-+_~.\d\w]
    |
    %[a-fA-f\d]{2,2}
  )*
)*
(
  \?
  (
    &?
    (
      [-+_~.\d\w]
      |
      %[a-fA-f\d]{2,2}
    )
    =?
  )*
)?
(
  #
  (
    [-+_~.\d\w]
    |
    %[a-fA-f\d]{2,2}
  )*
)?
$

我不会花时间实际完成所有这些部分的意思,但它看起来像是用于验证网址。

答案 2 :(得分:2)

  1. 了解正则表达式语法。

    sputnick的答案显示了学习语法含义的一种方法。还有很多正则表达式测试网站打破了正则表达式并解释了令牌的含义。

    您还可以参考教程或正在使用的语言的正则表达式文档以获取更多信息。 (阅读正确语言的文档非常重要,因为语言之间的正则表达式实现中存在细微差别。)

  2. 收集上下文/领域知识。

    查找写正则表达式的原因,或者正在使用的正则表达式是什么。这通常反映在注释或函数名称中。例如,如果在放入eval函数之前使用正则表达式来清理输入,那么您可能会想到一些攻击向量并检查正则表达式是否能够中和您的攻击。<​​/ p>

    在您的情况下,它是匹配的URL,因此您可以查看Wikipedia并参考与URL相关的RFC,并查找BNF语法。这是最好的情况,但即使没有这种情况,您可能已经预期/?#出现在正则表达式中。

  3. 分而治之

    您需要将正则表达式转换为“RAW”表单。例如,如果在字符串中指定了正则表达式,那么您需要对某些特殊字符进行额外的转义。您将在第一步中撤消该过程。在您的情况下,您使用的正则表达式使用/作为分隔符,因此您需要撤消/上完成的转义。

    ^(([\w]+:)?//)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$
    

    根据您的领域知识和正则表达式语法将正则表达式分解为大片段:

    ^
    (([\w]+:)?//)?
    (([\d\w]|%[a-fA-f\d]{2,2})+
    (:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?
    ([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}
    (:[\d]+)?
    (/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*
    (\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?
    (#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?
    $
    

    可以猜测以?#开头的部分分别是查询和片段。您还可以猜测单个/只能属于路径。您还可以猜测://彼此接近的部分最有可能是方案。 @表示与用户名和密码部分有关。通过上面的猜测,你可以达到我上面的一半。

    另一种启发式方法是将正则表达式分解为“顶级”标记(抽象语法树中的“顶级”)。通常,单个或几个“顶级”标记的组合对应于匹配文本中的某些有意义的部分。

    正如您已将正则表达式分解为大片段一样,如果您将正则表达式片段清晰映射到您尝试匹配的文本的相应部分,则可以独立处理每个片段

答案 3 :(得分:0)

您可以使用debuggex对其进行可视化。它会向您显示一个铁路图,并为您提供样本匹配,您可以逐步查看,以确切了解正则表达式中发生的情况。