正则表达式提取部分文件名

时间:2010-05-30 06:02:24

标签: c# regex parsing

我的文本文件格式如下:

R156484COMP_004A7001_20100104_065119.txt

我需要一致地提取R ****** COMP,004A7001号码,20100104(日期),而不关心065119号码。问题是并非所有被解析的文件都具有确切的命名约定。有些可能是这样的:

R168166CRIT_156B2075_SU2_20091223_123456.txt

R285476COMP_SU1_125A6025_20100407_123456.txt

那么我怎么能用regex而不是拆分来确保我总是得到那个序列号(例如004A7001),日期(例如20100104)和R ****** COMP(或者CRIT)???

以下是我现在所做的事情,但它只会像第一个例子那样获取格式化的文件。

if (file.Count(c => c == '_') != 3) continue;

进一步深入我的代码:

string RNumber = Path.GetFileNameWithoutExtension(file);

string RNumberE = RNumber.Split('_')[0];

string RNumberD = RNumber.Split('_')[1];

string RNumberDate = RNumber.Split('_')[2];

DateTime dateTime = DateTime.ParseExact(RNumberDate, "yyyyMMdd", Thread.CurrentThread.CurrentCulture);
string cmmDate = dateTime.ToString("dd-MMM-yyyy");

更新:这就是我现在所处的位置 - 我得到一个错误,将RNumberDate解析为实际的日期格式。 “无法将类型'RegularExpressions.Match'隐式转换为'string'

 string RNumber = Path.GetFileNameWithoutExtension(file);

 Match RNumberE = Regex.Match(RNumber, @"^(R|L)\d{6}(COMP|CRIT|TEST|SU[1-9])(?=_)", RegexOptions.IgnoreCase);

 Match RNumberD = Regex.Match(RNumber, @"(?<=_)\d{3}[A-Z]\d{4}(?=_)", RegexOptions.IgnoreCase);
 Match RNumberDate = Regex.Match(RNumber, @"(?<=_)\d{8}(?=_)", RegexOptions.IgnoreCase);



DateTime dateTime = DateTime.ParseExact(RNumberDate, "yyyyMMdd", Thread.CurrentThread.CurrentCulture);
string cmmDate = dateTime.ToString("dd-MMM-yyyy")

3 个答案:

答案 0 :(得分:3)

您可以使用多个正则表达式的强大功能来解决此问题。

compNumber:   /^R\d{6}(COMP|CRIT)(?=_)/
date:         /(?<=_)\d{8}(?=_)/
serialNumber: /(?<=_)\d{3}[A-Z]\d{4}(?=_)/

part:         /(?<=_).*?(?=_)/

分别在字符串上运行每个正则表达式以拉出部分。

答案 1 :(得分:1)

我不完全理解解析字符串的规则,但可能有用的建议是:

请查看RegEx.SplitRegEx.Matches以使用RegEx打破您的字符串。

创建您的RegEx,我建议excellent RegEx builder/checker/tutorial。使用该工具,您可以在大文本区域输入一串字符串(例如您的序列号或其他任何字符串),并以交互方式输入您的RegEx,查看当前匹配的部分。页面右侧有一个“教程”,可以帮助您学习如何构建RegEx。

答案 2 :(得分:1)

string filename = "R285476COMP_SU1_125A6025_20100407_123456.txt";

Match m = Regex.Match(filename,
    @"^(R\d+(?:COMP|CRIT))_(?:SU\d+_)?(\d+[A-Z]+\d+)_(?:SU\d+_)?(\d{8})_.*$",
    RegexOptions.IgnoreCase);

if (m.Success)
{
    Console.WriteLine(m.Groups[1].Value);    // R285476COMP
    Console.WriteLine(m.Groups[2].Value);    // 125A6025
    Console.WriteLine(m.Groups[3].Value);    // 20100407
}