查找和替换正则表达式问题

3
我开始掌握正则表达式,多亏了 SO 上其他问题的众多帮助。但是我仍然卡在这个问题上:
我的代码是:
   StreamReader reader = new StreamReader(fDialog.FileName.ToString());
   string content = reader.ReadToEnd();
   reader.Close();

我正在读取一个文本文件,我想搜索并更改此文本(我的文本文件中X和Y值总是相互跟随):
X17.8Y-1.
但是这个文本也可以是X16.1Y2.3(值在X和Y之后始终不同)
我想把它改成这样
X17.8Y-1.G54 或 X(value)Y(value)G54
我的正则表达式语句如下,但它没有起作用。
content = Regex.Replace(content, @"(X(?:\d*\.)?\d+)*(Y(?:\d*\.)?\d+)", "$1$2G54");

有人可以帮我修改一下吗,使它能够搜索X(通配符)Y(通配符),并用X(值)Y(值)G54替换它吗?
5个回答

2
您需要的正则表达式是:
X[-\d.]+Y[-\d.]+

以下是如何在C#中使用它的方法:
string content = "foo X17.8Y-1. bar";
content = Regex.Replace(content, @"X[-\d.]+Y[-\d.]+", "$0G54");
Console.WriteLine(content);

Output:

foo X17.8Y-1.G54 bar

现在这个正则表达式也匹配像 "X-17--2..3.-Y-...1." 这样的字符串,我认为他不想要这种情况。他在问题中最初提出的正则表达式专门过滤非数字表达式(它只接受像 .5 或 2.3 或 44 这样的数字)。这难道不会引入错误的匹配吗? - Chris Schmich
感谢您的修改。您是正确的,这种做法比使用\d更易读(对我来说也更易懂)。 - fraXis
@Chris Schmich:是的,原始表达式与我的正则表达式匹配不上所有字符串...这就是为什么它不起作用的原因。 :) 如果你仔细看他的例子,你会发现它不符合他的正则表达式所寻找的模式。 - Mark Byers
@Mark Byers:但现在你也匹配了我认为原始正则表达式从未“打算”匹配的字符串。似乎原始正则表达式只需要微调即可支持可选的负值,即@"(X-?(?:\d*\.)?\d+)*(Y-?(?:\d*\.)?\d+)",它支持问题中的两个示例,并仍然拒绝其他我认为应该被拒绝的情况(请参见我的上面的示例)。换句话说,我可以提出一个正则表达式X.*?Y.*?,它可以解决他的问题,但也会引入许多新问题。 - Chris Schmich
@Mark Byers:我的代码是基于原始正则表达式的,它有更多问题,不仅仅是处理负数。我认为下面gbacon的答案最准确。基本上,它是content = Regex.Replace(content, @"(X-?(\d+\.\d+|\d+\.|\.\d+|\d+))(Y-?(\d+\.\d+|\d+\.|\.\d+|\d+))", "$0G54");。它更冗长,但覆盖了所有情况并拒绝了其余部分。 - Chris Schmich

1
你的文本文件中“X(value)Y(value)”后面是什么?是空格?换行符?还是另一个“X(value)Y(value)”值对?
我不太擅长在正则表达式中使用快捷方式,比如\d,也不熟悉.NET,但我曾使用以下正则表达式来匹配值对:
(X[0-9.-]+Y[0-9.-]+)

而替换的内容是

$1G54

只要值对后面不直接跟着数字、句点或破折号,这个方法就能正常工作。

我个人非常喜欢[0-9]语法,而不是\d。它更易读,在正则表达式中,任何增强可读性的东西都是好事。 - Armstrongest

1

如果要挑剔输入,你可以使用

string num = @"-?(?:\d+\.\d+|\d+\.|\.\d+|\d+)";
content = Regex.Replace(content, "(?<x>X" + num + ")(?<y>Y" + num + ")", "${x}${y}G54");

在编程中,是否有一个可靠的Y值终止符?比如说空格:

content = Regex.Replace(content, @"(X.+?)(Y.+?)(\s)", "$1$2G54$3");

代码需要多强健?如果只是重写调试输出或其他快速且简单的任务,那就保持简单。

0

看起来您只需要支持可选的负数值:

content = Regex.Replace(content, @"(X-?(?:\d*\.)?\d+)*(Y-?(?:\d*\.)?\d+)", "$1$2G54");

1
当在我的测试用例上运行时,它会输出 "foo X17.8Y-1G54. bar"。 - Mark Byers
@Mark Byers:请看一下我对你回答的评论,我的确是错了。我是基于原始正则表达式进行修改,只是添加了负数的支持。原始正则表达式还存在其他问题。gbacon的回答最准确。 - Chris Schmich

0

我知道这并没有直接回答你的问题,但你应该看看Expresso。它是一个.NET正则表达式工具,可以让你调试、测试和微调复杂的表达式。它真的很方便。

虽然更像是自己动手解决问题的答案,但即使有人在这里给你答案,这个工具也会很有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接