0

我被要求修复其他人写的一行正则表达式。该表达式用于检查 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

5 回答 5

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

于 2013-02-25T21:15:26.717 回答
2
  1. 了解正则表达式语法。

    sputnick 的回答显示了一种学习语法含义的方法。还有很多正则表达式测试网站可以分解正则表达式并解释标记的含义。

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

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

    查找编写正则表达式的原因,或者正则表达式的用途。这通常反映在注释或函数名称中。例如,如果正则表达式用于在投入eval运行之前清理输入,那么您可能会想到一些攻击向量并检查正则表达式是否可以抵消您的攻击。

    在您的情况下,它是匹配 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})*)?
    $
    

    ?可以猜测以和开头的部分#分别是查询和片段。你也可以猜到single/只能属于path。你也可以猜出最有可能的方案是相互靠近:和靠近的部分。//@表示与用户名和密码部分有关。通过上面的猜测,你至少可以达到我上面的一半。

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

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

于 2013-02-25T22:27:41.000 回答
2

把它分成多行,然后一点一点地弄清楚。如果您不知道如何执行此操作,则需要学习更多的正则表达式语法以了解组、重复、交替和字符类的工作方式。

有一些网站可以帮助您查看这些片段是什么,例如,您可以将鼠标悬停在您在http://regexr.com上输入的正则表达式上,然后只看到突出显示和描述的片段,或者将其放入http://regexpal .com并以不同的颜色突出显示整个正则表达式。

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

^
(
  ([\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}
  )*
)?
$

我不会花时间去真正理解所有这些部分的含义,但在我看来,它就像是用于验证 URL。

于 2013-02-25T20:51:26.547 回答
0

将其提供给可视化工具。Regexper 之类的东西可以让您了解正在发生的事情。

在这种情况下,您似乎有一个用于解析 URI 的正则表达式。鉴于此,您通常最好将输入字符串提供给 URI 解析器并让其完成繁重的工作。您获得了所有好处,并且能够逐个操作对象。

于 2013-02-25T22:35:58.257 回答
0

您可以使用debuggex将其可视化。它将向您显示铁路图并为您提供示例匹配项,您可以逐步了解这些匹配项,以准确了解正则表达式中发生的情况。

于 2013-02-27T06:16:52.750 回答