以下代码来自我在此处提出的其他问题。每个人都非常乐于助人,我几乎掌握了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#代码中执行此操作。
答案 0 :(得分:1)
最简单的方法是使用一个简单的程序,使用一些捕获(命名)组的正则表达式模式,我有一点空闲时间,所以你去了:
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类定义:
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;
}
}
}
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();