通过通配符搜索和附加值查找和替换正则表达式

发布于 2024-08-31 16:10:35 字数 1450 浏览 3 评论 0原文

下面的代码来自我在这里提出的其他问题。每个人都非常有帮助,我几乎掌握了正则表达式,但我遇到了另一个障碍。


简而言之,这就是我基本上需要做的。我需要将文本文件中的这一行加载到内容变量中:


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.G54G0T6
G43Z0.1H5M08

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



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

  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.G54G0T6
G43Z0.1H5M08

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

有人可以修改我的正则表达式语句,以便我可以自动执行此操作吗?我尝试将两个正则表达式语句合并为一行,但失败了。


更新1:Stephen在下面的评论中建议,“正则表达式中没有算术运算符,您需要使用一个组来提取H值,然后将将其转换为 int,加一并构建一个新字符串。”。但我不知道如何在 C# 代码中执行此操作。

The below code is from my other questions that I have asked here on SO. Everyone has been so helpful and I almost have a grasp with regards to RegEx but I ran into another hurdle.

This is what I basically need to do in a nutshell. I need to take this line that is in a text file that I load into my content variable:

X17.8Y-1.Z0.1G0H1E1

I need to do a wildcard search for the X value, Y value, Z value, and H value. When I am done, I need this written back to my text file (I know how to create the text file so that is not the problem).

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

I have code that the kind users here have given me, except I need to create the T value at the end of the first line, and use the value from the H and increment it by 1 for the T value. For example:

X17.8Y-1.Z0.1G0H5E1

would translate as:

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

The T value is 6 because the H value is 5.

I have code that does everything (does two RegEx functions and separates the line of code into two new lines and adds some new G values). But I don't know how to add the T value back into the first line and increment it by 1 of the H value. Here is my code:

  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

This code works great at taking:

X17.8Y-1.Z0.1G0H5E1

and turning it into:

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

but I need it turned into this:

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

(notice the T value is added to the first line, which is the H value +1 (T = H + 1).

Can someone please modify my RegEx statement so I can do this automatically? I tried to combine my two RegEx statements into one line but I failed miserably.

Update1: Stephen in the comments below suggests, "there's no arithmetic operators in regex, you'll need to use a group to pull out the H value, turn it into an int, add one and build a new string.". But I have no idea on how to do this in C# code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

英雄似剑 2024-09-07 16:10:35

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

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());
                }
            }
        }
    }
}

With 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 的命令行参数读取输入和输出文件名,从而使程序可重用。

The easiest way to do this is with a simple program that uses a few Regex patterns that capture (named) groups, I had a little spare time so here you go:

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());
                }
            }
        }
    }
}

With input.txt containing:

X17.8Y-1.Z0.1G0H1E1

this program creates output.txt containing:

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

The above code in Program.cs requires the following simple Line and Fragment class definitions:

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;
        }
    }
}

Create a new C# Console Application project, add these three files, update your using statements and you're ready to go. You can very easily alter the code in Program.cs to read the input and output filenames from Main's command line arguments to make the program reusable.

我的鱼塘能养鲲 2024-09-07 16:10:35

我不确定您是否可以仅使用正则表达式来做到这一点,即使您可以,考虑到代码的可维护性,我也不会以这种方式实现它。使用 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();

I'm not sure you can do this just with Regular Expressions, and even in case you can, thinking on maintainability of the code, I wouldn't implement it that way. What you can easily do with RegEx, is to capture the pieces you need into groups, and from those create the output expression.
Here's the code for that:

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();
    }
}

And to get the output string you should do:

content.ToString();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文