我的时间字符串可能是以下格式之一(x
和y
- 整数数字, h 和 m - 符号):
x
h y
m x
ħy
M y
示例:
我应该写什么正则表达式来从这样的字符串中获取x
和y
个数字?
答案 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