2

我的文件名可以包含任意数量的单词/空格。基本上,我需要正确的语法来使用字符串中间的任何字符而不使用最后一个单词。

一些问题背景 - 第一个词或最后一个词可能是我需要捕捉的日期。或者,最后一个词可以是首字母。我需要命名捕获组中的日期/首字母。

示例文件,

FileName                                      Expected Capture Groups
--------                                      ----------------------
Myfile 120101.xls                             Date: {Myfile, 120101}
120101 MyFile.xls                             Date: {Myfile, 120101}
MyFile BHO.doc                                Date: {Myfile} Initials: {BHO}
120101 My file name BHO.docx                  Date: {120101} Initials: {BHO}
Foo.bar                                       None    
WhyDidIUsePeriods.huh.doc                     None
120101 WhyDidIUsePeriods.huh.doc              Date: {WhyDidIUsePeriods, 120101}
WhyDidIUsePeriods BHO.huh.doc                 Date: {WhyDidIUsePeriods} Initials: {BHO}
120101 WhyDidIUsePeriods BHO.huh.doc          Date: {120101} Initials: {BHO}

到目前为止,我有以下正则表达式:

@"^(?<Date>.+?(?= ))?.*?((?<Initials>(?<= )[^0-9]*?)|(?<Date>(?<= ).*?))?\..*?$"

这适用于两个字长的文件名,但不适用于更大的文件名(尾随组捕获多个单词)。问题是.*?在第一个 Date 捕获组之后。我需要这个来贪婪地捕捉所有“内部”词而不消耗最后一个词。我正在考虑负前瞻,但我不确定如何构造它,以便模式既消耗所有字符又不消耗与某个负前瞻模式匹配的字符( .*?\.)

(日期捕获组可以捕获非日期,稍后会有自定义解析逻辑)

我想要的东西是否可以通过负面的前瞻来实现?是否有更好的策略来满足这些要求?

编辑:

我已经说明了每个文件示例旁边的预期结果。我不想要任何更具体的日期正则表达式,因为它也可能是各种非数字格式。

不幸的是,Regex 是必要的,因为在某些情况下,问题.*?将被更具体的模式替换(例如,假设某些文件还需要包含单词“Foo”,Regex 似乎是最好的工具)。

4

1 回答 1

1

描述

该表达式将:

  • 假设文件名中唯一有趣的数据存在于第一个点之前
  • 假设首字母是三个大写字母,前面有一个空格,后面是一个点
  • 捕获文件名的非首字母和非日期部分
  • 捕获整个文件名,但不包括第一个点
  • 捕获首字母(如果存在)
  • 捕获日期(如果存在)
  • 如果文件名中存在日期、首字母和文件,则允许它们以任何顺序出现

为此,我正在使用

^
(?=(?:[^.]*?(?<file>(?<=^)[a-zA-Z\s]*?(?=\s[A-Z]{3}\.|\s)|(?<=\s)[a-zA-Z\s]*?(?=\.|\s[A-Z]{3}\.)))?)   # get the file (aka not date and not initials
(?=(?:[^.]*?\s(?<Initials>[A-Z]{3})\.)?)      # get the initials
(?=(?:[^.]*?(?<Date>\d+))?)   # capture the date value if it exists.
(?=(?<FileName>.*?)\.)     # capture entire filename upto but not including the first dot
.*

在此处输入图像描述

例子

现场演示

示例文本

Myfile 120101.xls
120101 MyFile.xls
MyFile BHO.doc
120101 My file name BHO.docx
Foo.bar
WhyDidIUsePeriods.huh.doc
120101 WhyDidIUsePeriods.huh.doc
WhyDidIUsePeriods BHO.huh.doc
120101 WhyDidIUsePeriods BHO.huh.doc

代码

Regex re = new Regex(@"^(?=(?:[^.]*?(?<file>(?<=^)[a-zA-Z\s]*?(?=\s[A-Z]{3}\.|\s)|(?<=\s)[a-zA-Z\s]*?(?=\.|\s[A-Z]{3}\.)))?)(?=(?:[^.]*?\s(?<Initials>[A-Z]{3})\.)?)(?=(?:[^.]*?(?<Date>\d+))?)(?=(?<FileName>.*?)\.).*",RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
MatchCollection mc = re.Matches(sourcestring);

火柴

[0][0] = Myfile 120101.xls    
[0][file] = Myfile
[0][Initials] = 
[0][Date] = 120101
[0][FileName] = Myfile 120101

[1][0] = 120101 MyFile.xls    
[1][file] = MyFile
[1][Initials] = 
[1][Date] = 120101
[1][FileName] = 120101 MyFile

[2][0] = MyFile BHO.doc    
[2][file] = MyFile
[2][Initials] = BHO
[2][Date] = 
[2][FileName] = MyFile BHO

[3][0] = 120101 My file name BHO.docx
[3][file] = My file name
[3][Initials] = BHO
[3][Date] = 120101
[3][FileName] = 120101 My file name BHO

[4][0] = Foo.bar
[4][file] = Foo
[4][Initials] = 
[4][Date] = 
[4][FileName] = Foo

[5][0] = WhyDidIUsePeriods.huh.doc    
[5][file] = WhyDidIUsePeriods
[5][Initials] = 
[5][Date] = 
[5][FileName] = WhyDidIUsePeriods

[6][0] = 120101 WhyDidIUsePeriods.huh.doc    
[6][file] = WhyDidIUsePeriods
[6][Initials] = 
[6][Date] = 120101
[6][FileName] = 120101 WhyDidIUsePeriods

[7][0] = WhyDidIUsePeriods BHO.huh.doc    
[7][file] = WhyDidIUsePeriods
[7][Initials] = BHO
[7][Date] = 
[7][FileName] = WhyDidIUsePeriods BHO

[8][0] = 120101 WhyDidIUsePeriods BHO.huh.doc
[8][file] = WhyDidIUsePeriods
[8][Initials] = BHO
[8][Date] = 120101
[8][FileName] = 120101 WhyDidIUsePeriods BHO
于 2013-08-02T03:33:28.113 回答