Meta-regular expressions?

本文关键字:expressions Meta-regular | 更新日期: 2023-09-27 18:06:44

我在前段时间编写了一个文件路由实用程序(. net),用于检查文件的位置和名称模式,并根据匹配将其移动到其他预配置的位置。相当简单,直接的东西。我已经包含了通过一系列正则表达式搜索和替换操作进行小转换的可能性,这些操作可以分配给文件"route",目的是添加标题行,用管道替换逗号,诸如此类。

现在我有了一个新的文本提要,它由一个文件头、一个批处理头和批处理下的大量详细记录组成。文件头包含文件中所有详细记录的计数,并且我被要求在分配的转换中"分割"文件,本质上为每个批处理记录生成一个文件。这也相当简单,但问题是,期望更新每个文件的文件头以反映细节计数。

我甚至不知道这是否可能与纯正则表达式。我是否可以计算给定文本文档中组的匹配次数并替换原始文本中的计数值,还是必须为这个文件编写自定义转换器?

如果我必须编写另一个转换器,是否有关于如何使其足够通用以可重用的建议?我正在考虑添加一个XSLT转换器选项,但是我对XSLT的理解不是很好。

有人让我举个例子。假设我有一个这样的文件:

FILE001DETAILCOUNT002
BATCH01
DETAIL001FOO
BATCH02
DETAIL001BAR

该文件将被分割并存储在两个位置。文件看起来像这样:

FILE001DETAILCOUNT001
BATCH01
DETAIL001FOO

FILE001DETAILCOUNT001
BATCH01
DETAIL001BAR

所以标签对我来说就是文件头的DETAILCOUNT值

Meta-regular expressions?

正则表达式本身不能计算它们所匹配的次数(或者,更好地说,它们不向regex用户公开),因此您确实需要额外的程序代码来跟踪这一点。

一个正则表达式只能捕获存在于源材料中的文本,它不能生成新的文本。所以除非你能在源代码的某个地方找到你需要的数字,否则你就不走运了。对不起。

我的程序首先将文本分成几批。

我想你会同意重新排序细节号是最棘手的部分。你可以用一个MatchEvaluator委托来做。

Regex.Replace (
   text, // the text replace part of
   @"(?<=^DETAIL)'d+", // the regex pattern to find.
   m => (detailNum++).ToString ("000"), // replacement (evaluated for each match)
   RegexOptions.Multiline);

查看前面的代码如何在每个批的开始增加detailNum

  var contents = 
@"FILE001DETAILCOUNT002
BATCH01
DETAIL001FOO
BATCH02
DETAIL001BAR";
  // foreach batch....
  foreach (Match match in Regex.Matches (contents, @"BATCH'd+'s+(?:(?!BATCH'd+).*'s*)+"))
  {
     Console.WriteLine ("=============='r'nFile'r'n================");
     int batchNum = 1;
     int detailNum = 1;
     StringBuilder temp = new StringBuilder ();
     TextWriter file = new StringWriter (temp);
     // Your file here instead of my stringBuilder/StringWriter
     string batchText = match.Value;
     int count = Regex.Matches (batchText, @"^DETAIL'd+", RegexOptions.Multiline).Count;
     file.WriteLine ("FILE001DETAILCOUNT{0:000}", count);
     string newText = Regex.Replace (batchText, @"(?<=^BATCH)'d+", batchNum.ToString ("000"), RegexOptions.Multiline);
     newText = Regex.Replace (
        newText, 
        @"(?<=^DETAIL)'d+", 
        m => (detailNum++).ToString ("000"), // replacement (evaluated for each match)
        RegexOptions.Multiline);
     file.Write (newText);
     Console.WriteLine (temp.ToString ());
  }

打印

==============
File
================
FILE001DETAILCOUNT001
BATCH001
DETAIL001FOO
==============
File
================
FILE001DETAILCOUNT001
BATCH001
DETAIL001BAR