C#使用Regex提取字符串日期时间信息失败,求解决方案
如何用C#正则提取字符串中的日期时间信息?
问题描述
尝试构建C#例程,通过正则表达式提取任意字符串中符合常见格式的日期时间信息,但代码运行后输出与输入完全一致,无法实现预期功能。
无效代码示例:
using System; using System.Text.RegularExpressions; class Program { public static string SearchForDateTime(string input) { // Define common date-time elements. string[] SEPARATORS = new string[] { "/", ":" }; string[] MONTHS = new string[] { "January", "February", /* etc. */ }; string[] DAYS = new string[] { "Monday", "Tuesday", /* etc. */ }; string[] HOURS = new string[] { "AM", "PM", "A.M.", "P.M.", /* etc. */ }; // Combine pattern elements, adding digitals. string separators = String.Join("|", SEPARATORS); string months = String.Join("|", MONTHS); string days = String.Join("|", DAYS); string hours = String.Join("|", HOURS); string pattern = $"{separators}|{months}|{days}|{hours}|[0-9]"; // Replace anything that is not a date-time element by an empty string. string output = Regex.Replace(input, $"[^{pattern}]", ""); return output; } static void Main(string[] args) { string input1 = "Hello John, today is 25 January 2024 10:15 AM in Miami"; string input2 = "Hello Jane, today is 25/01/2024 10:15P.M. in Boston"; Console.Write("Input 1: " + input1); Console.Write("Output 1: " + SearchForDateTime(input1)); Console.Write("Input 2: " + input2); Console.Write("Output 2: " + SearchForDateTime(input2)); } }
简化测试仅保留月份名称,结果仍然无效:
public static string SearchForDateTime(string input) { // Define common month elements. string[] MONTHS = new string[] { "January", "February", /* etc. */ }; // Combine pattern elements, adding digitals. string months = String.Join("|", MONTHS); string pattern = $"{months}"; // Replace anything that is not a month element by an empty string. string output = Regex.Replace(input, $"[^{pattern}]", ""); return output; }
问题原因分析
核心错误是误用正则字符类[]处理多字符模式:
- 字符类
[]的本质是匹配单个字符,任何放在其中的多字符序列(如January)、逻辑或符号|都会被拆解为单个字符处理。 - 例如
[^January|February]会被解析为「排除J、a、n、u、r、y、|、F、e、b等单个字符」,而非排除整个单词。因此输入中的空格、字母H/e/l等都不在排除范围内,替换后完全保留,导致输出与输入一致。 - 原始思路是"保留日期时间元素,删除其他",但字符类无法处理多字符的日期时间元素(如完整月份名、AM/P.M.),逻辑完全错误。
可行解决方案
推荐使用提取匹配项的思路,直接定位并提取所有符合日期时间格式的片段,而非通过替换删除无关内容,准确性更高。
修正后代码
using System; using System.Text.RegularExpressions; using System.Linq; class Program { public static string SearchForDateTime(string input) { // 定义常见日期时间的正则模式 string monthNames = @"January|February|March|April|May|June|July|August|September|October|November|December"; string dayNames = @"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday"; string timePattern = @"\d{1,2}:\d{2}\s*(?:AM|PM|A\.M\.|P\.M\.)"; string numericDatePattern = @"\d{1,2}[-/]\d{1,2}[-/]\d{2,4}"; string fullDatePattern = $@"{monthNames}\s+\d{{1,2}}\s+\d{{4}}"; // 组合所有模式,用非捕获分组避免多余分组匹配 string combinedPattern = $@"(?:{dayNames}|{fullDatePattern}|{numericDatePattern}|{timePattern})"; // 提取所有匹配项,忽略大小写兼容不同写法 var matches = Regex.Matches(input, combinedPattern, RegexOptions.IgnoreCase); // 拼接匹配结果,用空格分隔 return string.Join(" ", matches.Cast<Match>().Select(m => m.Value)); } static void Main(string[] args) { string input1 = "Hello John, today is 25 January 2024 10:15 AM in Miami"; string input2 = "Hello Jane, today is 25/01/2024 10:15P.M. in Boston"; Console.WriteLine("Input 1: " + input1); Console.WriteLine("Output 1: " + SearchForDateTime(input1)); Console.WriteLine("Input 2: " + input2); Console.WriteLine("Output 2: " + SearchForDateTime(input2)); } }
代码说明
- 精准匹配模式:针对不同日期时间格式(完整月日年、数字日期、时间格式、星期)分别定义正则,覆盖常见场景。
- 提取匹配项:用
Regex.Matches获取所有符合模式的片段,避免替换法的逻辑漏洞。 - 大小写兼容:添加
RegexOptions.IgnoreCase,支持am/AM、January/january等不同写法的匹配。 - 结果拼接:将所有匹配到的日期时间片段用空格拼接,输出干净的提取结果。
内容的提问来源于stack exchange,提问作者Douar Gwenn
相关产品推荐
相关产品推荐

