使用通配符搜索和添加值查找和替换RegEx

时间:2010-05-11 00:26:43

标签: c# regex replace find wildcard

以下代码来自我在此处提出的其他问题。每个人都非常乐于助人,我几乎掌握了RegEx,但我遇到了另一个障碍。


这就是我基本上需要做的事情。我需要把这行放在我加载到我的内容变量的文本文件中:


X17.8Y-1.Z0.1G0H1E1


我需要对X值,Y值,Z值和H值进行通配符搜索。当我完成后,我需要将其写回我的文本文件(我知道如何创建文本文件,这不是问题)。


X17.8Y-1.G54G0T2
G43Z0.1H1M08


我有这里的用户给我的代码,除了我需要在第一行的末尾创建T值,并使用H中的值并将其增加1作为T值。例如:


X17.8Y-1.Z0.1G0H5E1

将翻译为:

X17.8Y-1.G54G0的 T6
G43Z0.1H5M08

T值为6,因为H值为5.



我有代码执行所有操作(两个RegEx函数,并将代码行分成两个新行并添加一些新的G值)。但我不知道如何将T值添加回第一行并将其增加1的H值。这是我的代码:

  StreamReader reader = new StreamReader(fDialog.FileName.ToString());
  string content = reader.ReadToEnd();
  reader.Close();

  content = Regex.Replace(content, @"X[-\d.]+Y[-\d.]+", "$0G54G0");
  content = Regex.Replace(content, @"(Z(?:\d*\.)?\d+)[^H]*G0(H(?:\d*\.)?\d+)\w*", "\nG43$1$2M08"); //This must be created on a new line



这段代码非常适合:

X17.8Y-1.Z0.1G0H5E1

把它变成:

X17.8Y-1.G54G0
G43Z0.1H5M08


但我需要它变成这个:


X17.8Y-1.G54G0的 T6
G43Z0.1H5M08

(注意T值被添加到第一行,即H值+1(T = H + 1)。

有人可以修改我的RegEx声明,以便我可以自动执行此操作吗?我试图将我的两个RegEx语句组合成一行,但我失败了。


Update1 :Stephen在下面的评论中表示,“正则表达式中没有算术运算符,你需要使用一个组来提取H值,转它成为一个int,添加一个并构建一个新的字符串。“但我不知道如何在C#代码中执行此操作。

2 个答案:

答案 0 :(得分:1)

最简单的方法是使用一个简单的程序,使用一些捕获(命名)组的正则表达式模式,我有一点空闲时间,所以你去了:

Program.cs的

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            const string InputFileName = @"input.txt";
            const string OutputFileName = @"output.txt";

            List<Line> parsedLineList = new List<Line>();

            using (StreamReader sr = new StreamReader(InputFileName))
            {
                string inputLine;
                int lineNum = 0;

                while ((inputLine = sr.ReadLine()) != null)
                {
                    lineNum++;

                    Line parsedLine = new Line(inputLine);

                    if (parsedLine.IsMatch)
                    {
                        parsedLineList.Add(parsedLine);
                    }
                    else
                    {
                        Debug.WriteLine("Line {0} did not match pattern {1}", lineNum, inputLine);
                    }
                }
            }

            using (StreamWriter sw = new StreamWriter(OutputFileName))
            {
                foreach (Line line in parsedLineList)
                {
                    sw.WriteLine(line.ToString());
                }
            }
        }
    }
}

input.txt 包含:

<强> X17.8Y-1.Z0.1G0H1E1

此程序创建 output.txt ,其中包含:

<强> X17.8Y-1.G54G0T2
G43Z0.1H1M08

Program.cs中的上述代码需要以下简单的Line和Fragment类定义:

Line.cs

namespace Fragments
{
    class Line
    {
        private readonly static Regex Pattern =
            new Regex(@"^(?<X>X[^Y]+?)(?<Y>Y[^Z]+?)(?<Z>Z[^G]+?)(?<G>G[^H]+?)(?<H>H[^E]+?)(?<E>E[^$])$");

        public readonly string OriginalText;

        public string Text
        {
            get
            {
                return this.X.ToString() + this.Y.ToString() + this.G54.ToString() + this.G.ToString() + this.T.ToString() + Environment.NewLine +
                       this.G43.ToString() + this.Z.ToString() + this.H.ToString() + this.M08.ToString();
            }
        }

        public readonly bool IsMatch;

        public Fragment X { get; set; }
        public Fragment Y { get; set; }
        public readonly Fragment G54 = new Fragment("G54");
        public Fragment G { get; set; }
        public Fragment T { get; set; }
        public readonly Fragment G43 = new Fragment("G43");
        public Fragment Z { get; set; }
        public Fragment H { get; set; }
        public readonly Fragment M08 = new Fragment("M08");
        public Fragment E { get; set; }

        public Line(string text)
        {
            this.OriginalText = text;
            Match match = Line.Pattern.Match(text);
            this.IsMatch = match.Success;

            if (match.Success)
            {
                this.X = new Fragment(match.Groups["X"].Value);
                this.Y = new Fragment(match.Groups["Y"].Value);
                this.G = new Fragment(match.Groups["G"].Value);
                this.Z = new Fragment(match.Groups["Z"].Value);
                this.H = new Fragment(match.Groups["H"].Value);
                this.E = new Fragment(match.Groups["E"].Value);

                this.T = new Fragment('T', this.H.Number + 1.0);
            }
        }

        public override string ToString()
        {
            return this.Text;
        }
    }
}

Fragment.cs

namespace Fragments
{
    class Fragment
    {
        private readonly static Regex Pattern =
            new Regex(@"^(?<Letter>[A-Z]{1})(?<Number>.+)$");

        public readonly string Text;
        public readonly bool IsMatch;

        public readonly char Letter;
        public readonly double Number;

        public Fragment(string text)
        {
            this.Text = text;
            Match match = Fragment.Pattern.Match(text);
            this.IsMatch = match.Success;

            if (match.Success)
            {
                this.Letter = match.Groups["Letter"].Value[0];
                string possibleNumber = match.Groups["Number"].Value;

                double parsedNumber;
                if (double.TryParse(possibleNumber, out parsedNumber))
                {
                    this.Number = parsedNumber;
                }
                else
                {
                    Debug.WriteLine("Couldn't parse double from input {0}", possibleNumber);
                }
            }
            else
            {
                Debug.WriteLine("Fragment {0} did not match fragment pattern", text);
            }
        }

        public Fragment(char letter, double number)
        {
            this.Letter = letter;
            this.Number = number;
            this.Text = letter + number.ToString();
            this.IsMatch = true;
        }

        public override string ToString()
        {
            return this.Text;
        }
    }
}

创建一个新的C#控制台应用程序项目,添加这三个文件,更新您的using语句,然后就可以开始了。您可以非常轻松地更改Program.cs中的代码,以从Main的命令行参数中读取输入和输出文件名,以使程序可重用。

答案 1 :(得分:0)

我不确定你能用正则表达式做到这一点,即使你可以考虑代码的可维护性,我也不会那样实现它。使用RegEx可以轻松完成的工作是将所需的部分捕获到组中,并从中创建输出表达式。 这是代码:

System.Text.StringBuilder content = new System.Text.StringBuilder();
using (var reader = new StreamReader(fDialog.FileName.ToString()))
{
    string line = reader.ReadLine();
    while (line != null)
    {
        var matchingExpression = Regex.Match(line, @"(X[-\d.]+)(Y[-\d.]+)(Z(?:\d*\.)?\d+)[^H]*G0H((?:\d*\.)?\d+)\w*");

        content.AppendFormat(
            System.Globalization.CultureInfo.InvariantCulture,
            "{0}{1}G54G0T{2}\n",
            matchingExpression.Groups[0].Value,
            matchingExpression.Groups[1].Value,
            Int32.Parse(matchingExpression.Groups[3].Value) + 1);
        content.AppendFormat(
            System.Globalization.CultureInfo.InvariantCulture,
            "G43{0}H{1}M08\n", 
            matchingExpression.Groups[2].Value, 
            matchingExpression.Groups[3].Value);

        line = reader.ReadLine();
    }
}

要获得输出字符串,您应该这样做:

content.ToString();