在Python下:
ttsiod@elrond:~$ python
>>> import re
>>> a='This is a test'
>>> re.sub(r'(.*)', 'George', a)
'George'
在Perl下:
ttsiod@elrond:~$ perl
$a="This is a test";
$a=~s/(.*)/George/;
print $a;
(Ctrl-D)
George
在C#下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;
namespace IsThisACsharpBug
{
class Program
{
static void Main(string[] args)
{
var matchPattern = "(.*)";
var replacePattern = "George";
var newValue = Regex.Replace("This is nice", matchPattern, replacePattern);
Console.WriteLine(newValue);
}
}
}
不幸的是,C#打印:
$ csc regexp.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.5420
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
$ ./regexp.exe
GeorgeGeorge
这是C#正则表达式库中的错误吗?为什么它会打印“George”两次,当Perl和Python只打印一次?
答案 0 :(得分:5)
在你的例子中,差异似乎在于'replace'函数的语义,而不是在正则表达式处理本身。
.net正在进行“全局”替换,即它正在替换所有匹配,而不仅仅是第一场比赛。
Perl中的全局替换
(注意= ~s行末尾的小'g')
$a="This is a test";
$a=~s/(.*)/George/g;
print $a;
产生
GeorgeGeorge
在.NET中单个替换
var re = new Regex("(.*)");
var replacePattern = "George";
var newValue = re.Replace("This is nice", replacePattern, 1) ;
Console.WriteLine(newValue);
产生
George
因为它在第一次更换后停止。
答案 1 :(得分:2)
我不清楚它是否是一个错误,但是如果你将.*
更改为.+
它会做你想要的。我怀疑这是(.*)
匹配一个令人困惑的空字符串的事实。
这由以下代码支持:
using System;
using System.Text.RegularExpressions;
class Test
{
static void Main()
{
var match = Regex.Match("abc", "(.*)");
while (match.Success)
{
Console.WriteLine(match.Length);
match = match.NextMatch();
}
}
}
打印出3然后打印0.将图案更改为"(.+)"
会使其打印出来。
需要注意的一点是,这与C#作为一种语言无关 - 只有.NET标准库。值得区分语言和库 - 例如,如果您使用F#,VB,C ++ / CLI等.NET标准库,您将获得完全相同的行为。
答案 2 :(得分:2)
""
的替换为"George"
(.*
匹配""
)
和
"This is a start" == "This is a start" + ""
因此正则表达式匹配"This is a start"
并将其替换为"George"
,现在它的“光标”位于字符串的末尾,在那里他再次尝试匹配剩余的字符串({{1} })与模式。他有一场比赛,所以他增加了第二个""
。我不知道这是否正确。
我将补充说,Javascript引擎似乎在IE和Chrome下执行相同的操作(在此处测试:http://www.regular-expressions.info/javascriptexample.html)。
答案 3 :(得分:2)
这是C#
正则表达式库中的错误吗?
也许,但这并没有真正回答你的问题:
正则表达式 - C#的行为与Perl / Python不同
不同的正则表达式引擎和实现的行为方式不同。有时这是显式的(并且包括支持不同的正则表达式元素和语法:例如,使用\(
和\)
进行分组而不是使用反斜杠进行分组的普通括号。)
书Mastering Regular Expressions(Jeffrey EF Friedl,O'Reilly)花了很多时间来解释这些差异(除了非确定性有限自动机(NFA)和确定性有限自动机(DFA)之间的更基本差异之外)方法)。
PS。正如其他人注意.*
匹配空字符串,因此首先匹配并替换输入字符串的“all”,然后匹配并替换输入末尾的空字符串。如果你想匹配整个但可能是空的输入包括开头和结尾的锚点:^(.*)$
。