0

我目前有:

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday),?\s+(January|February|March|April|May|June|July|August|September|October|November|December)\s+[0-3]?[0-9],?\s+[0-2][0-9][0-9][0-9],?\s+([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9][0-9][0-9],?\s+(AM|PM)

...作为我的正则表达式,但是当使用一个小测试工具进行断言时,我发现它失败了。哪里搞砸了?我从网络应用程序获取日期时间文本并断言它与正则表达式匹配。

4

4 回答 4

6

错误的工作工具

事实上,试图修复您的正则表达式的所有其他答案都是关于您错误的正则表达式的不同部分;这应该告诉您它不是适合这项工作的工具。

正则表达式在短而紧凑的情况下很难正确,其中一个长度将是正确的噩梦,然后没有人能够在未来触摸它,因为害怕以某种神秘的方式破坏它。

惯用的 Java

SimpleDateFormat.parse()String是在 Java中以格式处理日期信息的惯用方式。

正则表达式用于匹配

有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题 - Jamie Zawinski

报价来自alt.religion.emacs邮件列表!

糟糕的解决方案来说明为什么SimpleDateFormat.parse()要做正确的事情。

无论如何,你可以用正则表达式匹配你想要的,但你不应该所有你想要做的验证。您将验证逻辑与匹配逻辑混为一谈,两者似乎在某些领域重叠,但在这种情况下,验证应该是代码,而不是正则表达式测试。

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (January|February|March|April|May|June|July|August|September|October|November|December) (\d{2}), (\d{4}) (\d{1,2}):(\d{2}):(\d{2})\.(\d{3}) (AM|PM)

上面的表达式将匹配您在标题中请求的字符串。但它不会尝试验证数字的范围,如果你这样做了,你将如何处理闰年和二月?,正则表达式维护起来会更糟。

在这种情况下,您应该使用正则表达式对数据进行分类以确保它模式或格式匹配,然后将其传递给真正的解析器或将组传递给实际执行范围验证的方法和其他事情。

于 2012-08-09T17:01:02.213 回答
0

正则表达式可能不是解析日期的最佳工具,但这是您的正则表达式中唯一让我印象深刻的东西。

您的时间似乎需要三位数的秒数,并且不包括毫秒:

([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9][0-9][0-9]

尝试将其更改为以下内容:

([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-9]{2}\.[0-9]{3}

请注意,如果要保存某些字符,也可以将所有 更改[0-9]为。\d

于 2012-08-09T16:58:32.773 回答
0

您已经省略了 Seconds 并且您:在正则表达式中使用 a 毫秒,但.在您的问题标题示例中使用 a 。所以试试:

(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday),?\s+(January|February|March|April|May|June|July|August|September|October|November|December)\s+[0-3]?[0-9],?\s+[0-2][0-9][0-9][0-9],?\s+([01]??[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9].[0-9][0-9][0-9],?\s+(AM|PM)
于 2012-08-09T17:00:26.160 回答
0

尽管我同意之前的发言者的观点,即正则表达式不适合这项工作,但这里有一个自动生成的片段,它将与您的确切日期相匹配:

import java.util.regex.*;

class Main
{
  public static void main(String[] args)
  {
    String txt="Wednesday, August 08, 2012 9:38:31.113 AM";

    String re1="((?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|Tues|Thur|Thurs|Sun|Mon|Tue|Wed|Thu|Fri|Sat))";    // Day Of Week 1
    String re2=".*?";   // Non-greedy match on filler
    String re3="((?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Sept|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?))";   // Month 1
    String re4=".*?";   // Non-greedy match on filler
    String re5="((?:(?:[0-2]?\\d{1})|(?:[3][01]{1})))(?![\\d])";    // Day 1
    String re6=".*?";   // Non-greedy match on filler
    String re7="((?:(?:[1]{1}\\d{1}\\d{1}\\d{1})|(?:[2]{1}\\d{3})))(?![\\d])";  // Year 1
    String re8=".*?";   // Non-greedy match on filler
    String re9="(\\d+)";    // Integer Number 1
    String re10=".*?";  // Non-greedy match on filler
    String re11="(\\d+)";   // Integer Number 2
    String re12=".*?";  // Non-greedy match on filler
    String re13="(\\d+)";   // Integer Number 3
    String re14=".*?";  // Non-greedy match on filler
    String re15="(\\d+)";   // Integer Number 4
    String re16=".*?";  // Non-greedy match on filler
    String re17="((?:[a-z][a-z]+))";    // Word 1

    Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6+re7+re8+re9+re10+re11+re12+re13+re14+re15+re16+re17,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(txt);
    if (m.find())
    {
        String dayofweek1=m.group(1);
        String month1=m.group(2);
        String day1=m.group(3);
        String year1=m.group(4);
        String int1=m.group(5);
        String int2=m.group(6);
        String int3=m.group(7);
        String int4=m.group(8);
        String word1=m.group(9);
        System.out.print("("+dayofweek1.toString()+")"+"("+month1.toString()+")"+"("+day1.toString()+")"+"("+year1.toString()+")"+"("+int1.toString()+")"+"("+int2.toString()+")"+"("+int3.toString()+")"+"("+int4.toString()+")"+"("+word1.toString()+")"+"\n");
    }
  }
}

如果一个人无论如何都故意想要可怕的正则表达式,那么网上有一个很棒的工具:http: //txt2re.com/

于 2012-08-09T17:23:18.480 回答