代码之家  ›  专栏  ›  技术社区  ›  EndangeredMassa

如何在此正则表达式中指定可选的捕获组?

  •  5
  • EndangeredMassa  · 技术社区  · 17 年前


    .*(header_\d{10,11}_).*(_.*_\d{8}).*(\.\w{3,4}).*
    -------------------------------------------
    .*                   # Ignore some garbage in the front
    (header_             # Match the start of the file name,
        \d{10,11}_)      #     including the ID (10 - 11 digits)
    .*                   # Ignore the type code in the middle
    (_.*_\d{8})          # Match some random characters, then an 8-digit date
    .*                   # Ignore anything between this and the file extension
    (\.\w{3,4})          # Match the file extension, 3 or 4 characters long
    .*                   # Ignore the rest of the string
    


    我希望这与以下字符串匹配:

    str1 = "header_0000000602_t_mc2e1nrobr1a3s55niyrrqvy_20081212[1].doc [Compatibility Mode]"
    str2 = "Microsoft PowerPoint - header_00000000076_d_al41zguyvgqfj2454jki5l55_20071203[1].txt"
    str3 = "header_00000000076_d_al41zguyvgqfj2454jki5l55_20071203[1]"
    


    其中,捕获组返回如下内容:

    $1  =  header_0000000602_
    $2  =  _mc2e1nrobr1a3s55niyrrqvy_20081212
    $3  =  .doc
    


    其中,如果找不到文件扩展名,则$3可以为空$3是可选部分,如上面的str3所示。

    我觉得在第三个捕获组的末尾使用“?”是合适的做法,但它并没有像我预期的那样起作用。我可能太天真了,“*”部分,我用它来忽略字符串的一部分。


    .*(header_\d*_).*(_.*_.{8}).*(\.\w{3,4})?.*
    
    7 回复  |  直到 17 年前
        1
  •  5
  •   Sean Bright Sean Stinehour    17 年前

    一种可能性是,第二个是最后一个 .*

    .*(header_\d*_).*(_.*_.{8}).*?(\.\w{3,4})?.*
                                 ^ Added that
    

    这是不正确的,这一个将匹配您提供的输入,但它假设第一个 . 它是文件扩展名的开始:

    .*(header_\d*_).*(_.*_.{8})[^\.]*(\.\w{3,4})?.*
    

        2
  •  3
  •   Eddie    17 年前

    我相信问题出在你的第三个问题上 .* ,您在上面用“忽略此文件与文件扩展名之间的任何内容”对其进行了注释。它是贪婪的,所以它可以匹配任何东西。当您将扩展模式设置为可选时,第三个 .* . '字符,您可以替换 .* [^.]* 在你恢复系统后,剩下的部分有望发挥作用 ?

        3
  •  2
  •   Factor Mystic    17 年前

    .* 可能是启动正则表达式的错误方法-它将匹配0或更多( * header 这就是你想要的。您也可以将其替换为 \w ,它与分词符匹配。我还建议使用以下工具: The Regex Coach

        4
  •  2
  •   David Morton    17 年前

    在第二个匹配中指定只希望匹配所有不含句点的字符 然后 为您的分机进行匹配。

    ".*(header_\d{10,11}_).*(_.*_\d{8})[^.]*(\.\w{3,4})?"
    
        5
  •  2
  •   Gavin Miller    17 年前

    这是你的正确结果

    .*?(header_\d*_).*?(_.*_.{8})[^.]*(\.\w{3,4})?.*
    -------------------------------------------
    .*?                  # Prevent a greedy match
    (header_             # 
        \d{10,11}_)      # 
    .*?                  # Prevent a greedy match
    (_.*_\d{8})          # 
    [^.]*                # Take everything that is NOT a period
    (\.\w{3,4})          # Match the extension
    .*                   # 
    

    隐含的假设是,周期将是数字匹配后文件扩展名的开始。以下内容不符合此要求:

    string unmatched = "header_00000000076_d_al41zguyvgqfj2454jki5l55_20071203[1].foobar.txt"
    

    ,在.NET中取出组时,请确保代码如下所示:

    regex.Match(string_to_match).Groups[1].Value
    regex.Match(string_to_match).Groups[2].Value
    regex.Match(string_to_match).Groups[3].Value
    

    // 0 index == string_to_match
    regex.Match(string_to_match).Groups[0].Value
    regex.Match(string_to_match).Groups[1].Value
    regex.Match(string_to_match).Groups[2].Value
    

    这件事一开始就把我绊倒了。

        6
  •  1
  •   Daniel Schaffer    17 年前

    这适用于您发布的示例:

    ^.*?(?<header>\d+)_.*?_(?<date>\d{8}).*?(?:\.(?<ext>\w{3,4}))?[\w\s\[\]]*$
    

    如果文件名后的文本包含除[和]以外的任何非字母数字字符,则需要修改模式。

        7
  •  1
  •   Scott Willeke    17 年前

    以下是一个适用于您发布内容的方法:

    ^.*(?<header>header_\d{10,11})_.*(?<date>_[a-z0-9]+_\d{8})(\[\d+\])(?<ext>(\.[a-zA-Z0-9]{3,4})?).*
    

    替换为:

    Header: $1
    Date: $2
    Extension: $4
    

    推荐文章