这个正则表达式的含义是什么?

时间:2013-01-12 06:06:45

标签: regex perl

我有一个正则表达式定义跟随匹配http urls,任何人都可以帮助用英语解释?

^/foo/.*(?<!\.css|\.js|\.jpg)$

4 个答案:

答案 0 :(得分:6)

目录/foo或更低版本中的任何文件或目录都不是cssjsjpg文件。

^        start of string anchor
/foo/    literal "/foo/"
.*       any number of characters
(?<!...) match from here backwards must fail:
  \.     dot
  css    literal "css"
  |      or
$        end of string anchor

所以,开始字符串,/foo/,也许是其他一些字符,然后是字符串结尾 - 但就在之前,不能是.css.js.jpg

编辑:抱怨顽固。对于大多数引擎来说,它确实是一个无效的正则表达式,包括Perl。原因是,负面的背后必须有固定的宽度;这个lookbehind可以是四个字符(如果是.jpg.css)或三个字符(.js)。修复是在lookbehind中插入一个额外的“匹配任何东西”,这样宽度总是四:

^/foo/.*(?<!\.css|.\.js|\.jpg)$

有了它,它起作用:

perl -e 'print "/foo/bar" =~ m[^/foo/.*(?<!\.css|.\.js|\.jpg)$];'
=> 1
OP:你的regexpal.com的问题在于他们测试JavaScript正则表达式,它们根本没有实现负面的lookbehind。 Regexp方言的细节不同。

答案 1 :(得分:4)

您的模式应与以下内容相匹配:

m{^/foo/} && !m{\.(?:css|js|jpg)\z}

这是更具可读性,我不需要解释它。与模式不同,它还具有实际编译的优势。

>perl -c -e"m{^/foo/.*(?<!\.css|\.js|\.jpg)$}"
Variable length lookbehind not implemented in regex m/^/foo/.*(?<!\.css|\.js|\.jpg)$/ at -e line 1.

答案 2 :(得分:3)

匹配

的任何字符串
  1. /foo/
  2. 开头
  3. 其他任何内容
  4. 不以.css.js.jpg
  5. 结尾

    因此它匹配根目录foo下的任何文件(直接或作为子目录),而不是CSS,JS或JPG。

答案 3 :(得分:2)

使用YAPE::Regex::Explain学习正则表达式。检查以下代码:

#!/usr/bin/perl -w
use strict;
use YAPE::Regex::Explain;
my $regex = '^/foo/.*(?<!\.css|\.js|\.jpg)$';
print YAPE::Regex::Explain->new($regex)->explain();

输出:

The regular expression:

(?-imsx:^/foo/.*(?<!\.css|\.js|\.jpg)$)

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
----------------------------------------------------------------------
  /foo/                    '/foo/'
----------------------------------------------------------------------
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
----------------------------------------------------------------------
  (?<!                     look behind to see if there is not:
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    css                      'css'
----------------------------------------------------------------------
   |                        OR
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    js                       'js'
----------------------------------------------------------------------
   |                        OR
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    jpg                      'jpg'
----------------------------------------------------------------------
  )                        end of look-behind
----------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------