使用正则表达式解析时间字符串

时间:2011-08-02 08:15:57

标签: regex

我的时间字符串可能是以下格式之一(xy - 整数数字, h m - 符号):

  • x h y m
  • xħ
  • y M
  • y

示例:

  • 1h 20m
  • 45米
  • 2H
  • 120

我应该写什么正则表达式来从这样的字符串中获取xy个数字?

5 个答案:

答案 0 :(得分:4)

(\d+)([mh]?)(?:\s+(\d+)m)?

然后,您可以检查组1-3。对于你的例子,那些将是

('1', 'h', '20')
('45', 'm', '')
('2', 'h', '')
('120', '', '')

与往常一样,您可能希望使用一些锚点^$\b ......

答案 1 :(得分:3)

由于您的用户名,我假设您正在使用.NET。 :)

我认为在这种情况下,使用TimeSpan.ParseExact来完成此任务会更容易。

您可以根据这些格式指定ParseExact中允许的格式列表(see here for the format for these)和TimeSpan

以下是一个例子:

var formats = new[]{"h'h'", "h'h 'm'm'", "m'm'", "%m"};
    // I have assumed that a single number means minutes

foreach (var item in new[]{"23","1h 45m","1h","45m"})
{   
    TimeSpan timespan;
    if (TimeSpan.TryParseExact(item, formats, CultureInfo.InvariantCulture, out timespan))
    {
        // valid
        Console.WriteLine(timespan);
    }
}

输出:

00:23:00
01:45:00
01:00:00
00:45:00

唯一的问题是它相当不灵活。中间的其他空格将无法验证。使用Regex的更强大的解决方案是:

var items = new[]{"23","1h 45m", "45m", "1h", "1h 45", "1h   45", "1h45m"};
foreach (var item in items)
{
    var match = Regex.Match(item, @"^(?=\d)((?<hours>\d+)h)?\s*((?<minutes>\d+)m?)?$", RegexOptions.ExplicitCapture);
    if (match.Success)
    {       
        int hours;
        int.TryParse(match.Groups["hours"].Value, out hours); // hours == 0 on failure

        int minutes;
        int.TryParse(match.Groups["minutes"].Value, out minutes);

        Console.WriteLine(new TimeSpan(0, hours, minutes, 0));
    }
}

正则表达式的细分:

  • ^ - 字符串开头
  • (?=\d) - 必须以数字开头(这样做是因为这两部分都标记为可选,但我们要确保至少有一部分存在)
  • ((?<hours>\d+)h)? - 小时(可选,捕获到命名组)
  • \s* - 空格(可选)
  • ((?<minutes>\d+)m?)? - 分钟(可选,捕获到命名组,'m'也是可选的)
  • $ - 字符串结尾

答案 2 :(得分:1)

我会说mhyfritz'解决方案简单,高效且好,如果你的输入只是你所展示的。 如果您需要处理极端情况,可以使用更具辨别力的表达式:

^(\d+)(?:(h)(?:\s+(\d+)(m))?|(m?))$

但它可能有点过分......

(如果你需要在更大的文本体中检测这种模式,那就去掉^和$。)

答案 3 :(得分:1)

试试这个:^(?:(\d+)h\s*)?(?:(\d+)m?)?$

var s = new[] { "1h 20m", "45m", "2h", "120", "1m 20m" };

foreach (var ss in s)
{
    var m = Regex.Match(ss, @"^(?:(\d+)h\s*)?(?:(\d+)m?)?$");

    int hour = m.Groups[1].Value == "" ? 0 : int.Parse(m.Groups[1].Value);
    int min = m.Groups[2].Value == "" ? 0 : int.Parse(m.Groups[2].Value);

    if (hour != 0 || min != 0)
        Console.WriteLine("Hours: " + hour + ", Mins: " + min);
    else
        Console.WriteLine("No match!");
}

答案 4 :(得分:0)

在bash中

echo $string | awk '{for(i=1;i<=NF;i++) print $i}' | sed s/[hm]/""/g