A: 

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();
Anero
@Anero At quick glance of your code I don't see where you are adding the T value back to the end of G54G0 (ex G54G0T6; if H is H5). Thanks.
fraXis
@Anero I could not get your code to execute correctly. It had errors such as 'string' does not contain a definition for AppendLine. The same error for AppendFormat, and CultureInfo does not exist in the current context.
fraXis
AppendLine and AppendFormat are methods of StringBuilder class not string (which is the type of "content" on my code snippet). To use it and CultureInfo, you should add "using System.Text;" and "using System.Globalization;" on top of the .cs file (without the quotes obviously). Also, you're right about the T value, I misplaced the regular expression that captures and add 1 to its value (it's on the second line in my code snippet). I'll recreate the regular expression later and correct the snippet.
Anero
+1  A: 

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.

Peter McGrattan
Thank you so much for taking the time to do this for me. I appreciate it greatly. Thanks.
fraXis