如何自动替换捕获组

时间:2013-08-21 13:47:19

标签: c# regex

假设我有一个与某个文件模式匹配的源文件,我希望文件模式的某些元素可以在新创建的目标文件中重用。
所以对于前正则表达式中给出的指定文件模式是

src_pattern = "(\d\d)_(\d\d)_(\d\d\d\d)_FOO.xml";

after searching a directory, found a matching source file looking like 

src = 08_21_2013_foo.xml

now the new file must be of the form 

dst = $3$1$2_BAR.xml;  

捕获组从源中拉出(因此看起来像20130821_BAR.xml)。我如何有效地完成这项工作,需要非常灵活,我不知道每个人看起来是什么样的,他们是从其他地方撤出的。所以我猜我在抓取捕获组的编号方面遇到了麻烦,即第3个,第1个,然后是第2个,让我们说我发现了它,如何将它引用回源文件。我是否必须有一个表示数字的整数(比如k)并引用它

match = Regex.Match(src, src_pattern)
match.Groups[k].Value
拉这些编号似乎很痛苦......

我也不知道每个dst指定了多少这些捕获组,所以如何自动完成所有这些?这个

还有其他方式或智能本地功能吗?

3 个答案:

答案 0 :(得分:1)

尝试

var rx = new Regex(@"^(\d\d)_(\d\d)_(\d\d\d\d)(?=_FOO\.xml$)", RegexOptions.IgnoreCase);
var res = rx.Replace("08_21_2013_foo.xml", "$3$1$2");

注意RegexOptions.IgnoreCase,使用^$强制正则表达式考虑整个字符串,(?=_FOO.xml$)表示"followed by _FOO(end of the string)",但那不是一个捕获组。

答案 1 :(得分:1)

  • 因此我们采用正则表达式并提供一些示例数据。
  • 用于mockMatches中的每个匹配项,您将使用提取文件名列表的枚举器替换它。
  • 然后我们使用src_pattern匹配正则表达式并打开忽略大小写。
  • 然后我们希望匹配的组以GroupCollection形式出现,因此我们Cast<T>()可枚举为IEnumerable<Group>
  • 使用Skip(1)
  • 跳过第一组(即整场比赛)
  • 然后使用.Select(a=>a.Value)
  • 获取组的值(组匹配的实际文本)
  • 使用_作为.Aggregate((s1,s2)=>s1+"_"+s2)
  • 的分隔符加入所有这些
  • 然后添加文件结束常量"_bar.xml"

Linqpad回答:

var src_pattern= @"(\d\d)_(\d\d)_(\d\d\d\d)_FOO\.xml";
var mockMatches = new[]{"08_21_2013_foo.xml"};
foreach(var mm in mockMatches){
  var match = Regex.Match(mm,src_pattern, RegexOptions.IgnoreCase).Dump();
  var dst= match.Groups.Cast<Group>().Skip(1).Select(a=>a.Value).Aggregate((s1,s2)=>s1+"_"+s2)+"_bar.xml";
  dst.Dump();
}

答案 2 :(得分:1)

如果您可以让他们使用名为的群组(http://msdn.microsoft.com/en-us/library/bs2twtah.aspx#named_matched_subexpression),您可以轻松地根据他们请求的内容运行替代品,并让他们在结果输出dst中再次命名。例如:

src_pattern = "(<first>\d\d)_(<second>\d\d)_(<third>\d\d\d\d)_FOO.xml";

after searching a directory, found a matching source file looking like 

src = 08_21_2013_foo.xml

now the new file must be of the form 

dst = "[third][first][second]_BAR.xml";