【问题标题】:Understand this RegEx statement理解这个 RegEx 语句
【发布时间】:2011-01-18 09:03:13
【问题描述】:

我正在尝试详细了解此 RegEx 语句。它应该从 ASP.Net FileUpload 控件验证文件名以仅允许 jpeg 和 gif 文件。它是别人设计的,我不完全理解。它在 Internet Explorer 7.0 中运行良好,但在 Firefox 3.6 中运行良好。

<asp:RegularExpressionValidator id="FileUpLoadValidator" runat="server" 
     ErrorMessage="Upload Jpegs and Gifs only." 
     ValidationExpression="^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$"
     ControlToValidate="LogoFileUpload">
</asp:RegularExpressionValidator>

【问题讨论】:

  • 不知道为什么这会被否决。
  • 因为它要求人们为他钓鱼,而不是教他钓鱼。 3票真的吗?我猜一百万个“这个正则表达式是什么意思”的问题。
  • 我同意布赖恩的观点,这太荒谬了。
  • 布赖恩。那么,您是否建议人们阅读书籍而不是使用 StackOverflow 来获得答案?
  • 我花了一段时间,但我找到了为什么它不适用于 Firefox。 Firefox v3.x 不允许 JavaScript 从文件输入字段中获取完整路径名,这个特定的正则表达式希望看到完整路径名。

标签: c# asp.net regex file-upload validation


【解决方案1】:

这里有一个简短的解释:

^               # match the beginning of the input
(               # start capture group 1
  (             #   start capture group 2
    [a-zA-Z]    #     match any character from the set {'A'..'Z', 'a'..'z'}
    :           #     match the character ':'
  )             #   end capture group 2
  |             #   OR
  (             #   start capture group 3
    \\{2}       #     match the character '\' and repeat it exactly 2 times
    \w+         #     match a word character: [a-zA-Z_0-9] and repeat it one or more times
  )             #   end capture group 3
  \$?           #   match the character '$' and match it once or none at all
)               # end capture group 1
(               # start capture group 4
  \\            #   match the character '\'
  (             #   start capture group 5
    \w          #     match a word character: [a-zA-Z_0-9] 
    [\w]        #     match any character from the set {'0'..'9', 'A'..'Z', '_', 'a'..'z'}
    .*          #     match any character except line breaks and repeat it zero or more times
  )             #   end capture group 5
)               # end capture group 4
(               # start capture group 6
  .             #   match any character except line breaks
  jpg           #   match the characters 'jpg'
  |             #   OR
  .             #   match any character except line breaks
  JPG           #   match the characters 'JPG'
  |             #   OR
  .             #   match any character except line breaks
  gif           #   match the characters 'gif'
  |             #   OR
  .             #   match any character except line breaks
  GIF           #   match the characters 'GIF'
)               # end capture group 6
$               # match the end of the input

编辑

根据部分cmets的要求,以上是我自己写的一个小工具生成的。你可以在这里下载:http://www.big-o.nl/apps/pcreparser/pcre/PCREParser.html(警告:正在大量开发中!)

编辑 2

它将匹配如下字符串:

x:\abc\def\ghi.JPG
c:\foo\bar.gif
\\foo$\baz.jpg

以下是第 1、4 和 6 组分别匹配的内容:

group 1 | group 4      | group 6
--------+--------------+--------
        |              |
 x:     | \abc\def\ghi | .JPG
        |              |
 c:     | \foo\bar     | .gif
        |              |
 \\foo$ | \baz         | .jpg
        |              |

请注意,它还匹配c:\foo\bar@gif 之类的字符串,因为 DOT 匹配任何字符(换行符除外)。它会拒绝像c:\foo\bar.Gif这样的字符串(gif中的大写G)。

【讨论】:

  • 我可以无知的问一下你用的是什么工具吗?
  • Bart K。能否请您发布允许进行这种解析的 URL?
  • +1 详细!我也想知道这是否是由工具产生的。
  • 幸好我重新加载了,所以我没有继续做同样该死的事情。 +++
  • Bart K。我了解其中的每个元素,但并非所有元素都联系在一起。
【解决方案2】:

这是一个糟糕的正则表达式。

^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$

让我们一步一步来。

([a-zA-Z]:)

这要求文件路径以驱动器号开头,例如C:、d: 等。

(\\{2}\w+)\$?)

\\{2} 表示反斜杠重复两次(注意\ 需要转义),然后是一些字母数字(\w+),然后可能是一个美元符号(\$?)。这是 UNC 路径的主机部分。

([a-zA-Z]:)|(\\{2}\w+)\$?)

| 表示“或”。因此,要么以驱动器号或 UNC 路径开头。恭喜你踢出非 Windows 用户。

(\\(\w[\w].*))

这应该是路径的目录部分,但实际上是 2 个字母数字后跟除新行 (.*) 之外的任何内容,例如 \ab!@#*(#$*)。

这部分的正确正则表达式应该是(?:\\\w+)+

(.jpg|.JPG|.gif|.GIF)$

这意味着路径的最后 3 个字符必须是 jpg、JPG、gif 或 GIF。请注意,. 不是一个点,而是匹配除\n 之外的任何内容,因此像haha.abcgif 或malicious.exe\0gif 这样的文件名将通过。

这部分的正确正则表达式应该是\.(?:jpg|JPG|gif|GIF)$

一起,

^(([a-zA-Z]:)|(\\{2}\w+)\$?)(\\(\w[\w].*))(.jpg|.JPG|.gif|.GIF)$

将匹配

D:\foo.jpg
\\remote$\dummy\..\C:\Windows\System32\Logo.gif
C:\Windows\System32\cmd.exe;--gif

会失败

/home/user/pictures/myself.jpg
C:\a.jpg
C:\d\e.jpg

正确的正则表达式是/\.(?:jpg|gif)$/i,并检查上传的文件是否真的是服务器端的图像。

【讨论】:

  • 哇!非常感谢您提供详细信息。这就是我一直在寻找的。解决了我的问题。仍然很好奇为什么 original 在 Firefox 中不起作用。可能是单独问题的主题,但可能与这里的主要主题不太相关。
  • 对不起。刚刚发现 '' 不适用于 'C:\doc\My Pictures\cat-fish.gif'
【解决方案3】:

它将文件名拆分为部分驱动器号、路径、文件名和扩展名。

很可能 IE 使用反斜杠,而 FireFox 使用斜杠。尝试用 [\\/] 替换 \\ 部分,以便表达式同时接受斜杠和反斜杠。

【讨论】:

  • 不。用 [\\\/] 交换 \\ 没有帮助。仍然无法在 Firefox 中运行。
【解决方案4】:

来自 Expresso 这是 Expresso 所说的:

/// 正则表达式的描述: /// /// 行或字符串的开头 /// [1]:一个编号的捕获组。 [([a-zA-Z]:)|(\\{2}\w+)\$?] /// 从 2 个选项中选择 /// [2]:一个编号的捕获组。 [[a-zA-Z]:] /// [a-zA-Z]: /// 此类中的任何字符:[a-zA-Z] /// : /// (\\{2}\w+)\$? /// [3]:一个编号的捕获组。 [\\{2}\w+] /// \\{2}\w+ /// 字面量 \,正好 2 次重复 /// 字母数字,一个或多个重复 /// 字面量 $,零次或一次重复 /// [4]:一个编号的捕获组。 [\\(\w[\w].*)] /// \\(\w[\w].*) /// 字面量\ /// [5]:一个编号的捕获组。 [\w[\w].*] /// \w[\w].* /// 字母数字 /// 此类中的任何字符:[\w] /// 任意字符,任意重复次数 /// [6]:一个编号的捕获组。 [.jpg|.JPG|.gif|.GIF] /// 从 4 个选项中选择 /// .jpg /// 任意字符 /// jpg /// .JPG /// 任意字符 /// JPG /// .gif /// 任意字符 /// gif /// .GIF /// 任意字符 /// 动图 /// 行尾或字符串 ///

希望这会有所帮助, 最好的祝福, 汤姆。

【讨论】:

    【解决方案5】:

    您可能需要实施服务器端验证。看看这篇文章。

    Solving the Challenges of ASP.NET Validation

    此外,还有一些很好的在线工具可用于创建或解释正则表达式。但我怀疑问题不在于表达式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多