使用正则表达式识别字符序列并使用它构建字符串

时间:2014-09-17 08:56:10

标签: c# regex stringbuilder

我有一个令牌器,其中令牌具有给定的接口:

interface IToken
{
    string Str { get; } //used after the token is built to get its content
    bool Success { get; } //has the informaition if the last 'TryAdd' was a success
    bool Valid { get; } //has the information if the current 'Str' is complete and Valid
    void TryAdd(char c); //Is called to add the next character to the token      
}

一般的想法是,并行处理给定输入的每个字符的已实现令牌列表。

'NumberToken'太慢了,我试着加快速度。我想试用正则表达式,我想知道以下是否可行。

给定像String patternINTFRACEXP = @"(\A)[0-9]+?\.[0-9]+?[eE]{1}[+-]{0,1}[0-9]+?(\Z)";这样的模式,我可以通过一次添加一个字符来逐步检查表达式是否仍然有效。我写了一些Pseudocode来说明我希望那个构建器做什么。

class PseudoCode : IToken
{
    String patternINTFRACEXP = @"(\A)[0-9]+?\.[0-9]+?[eE]{1}[+-]{0,1}[0-9]+?(\Z)";

    RegexBuilder builder;

    public PseudoCode()
    {
        builder = new RegexBuilder(patternINTFRACEXP);
        Success = true;
    }

    public string Str{ get { return builder.ToString(); } }

    public bool Success { get; private set; }

    public bool Valid { get { return builder.IsMatch(); } }

    public void TryAdd(char c) { Success &= builder.TryAdd(c); }
}

StringBuilder和Regex的组合是否已存在?

实施(builder as RegexBuilder).TryAdd(c as Char);的方法是什么?

1 个答案:

答案 0 :(得分:1)

我的方法是从模式的不同步骤开始,从最长的

开始
([0-9]+\.[0-9]+[eE]{1}[+-]{0,1}[0-9]+|[0-9]+?\.[0-9]+[eE]{1}[+-]{0,1}[0-9]+|[0-9]+\.[0-9]+[eE]{1}[+-]{0,1}|[0-9]+\.[0-9]+[eE]{1}|[0-9]+\.[0-9]+|[0-9]+\.|[0-9]+)

DEMO HERE

我不熟悉c#,jsut在正则表达式部分回答,不需要ungreedy运算符,因为你有'分隔符'(。,+, - ,e)已经分割了字符串。

我会用这样的不同部分做一个数组:

pattern = ["[0-9]+","\.","[0-9]+","[eE]{1}","[+-]{0,1}","[0-9]+"]
testpattern = ""
pattern.each do |p|
  testpattern += "#{testpatern}#{p}|#{testpattern}" 
end
testpattern.rstrip("|") 

使用testpatern进行测试。 (剥离领先|最后)

它的ruby代码并没有经过测试,所以我可能在某个地方有一个bug,但想法是在每次迭代时构建模式添加新部分,最后用完整的ORed正则表达式进行测试。

希望这会有所帮助

替代解决方案: ^([0-9]+)[.]?([0-9]+|)(?:[eE]{1}([+-]{0,1}[0-9]+|)|)$

Updated DEMO

它完全匹配(如果在格式中没有预期的东西它将不匹配)并捕获整数部分,小数部分和带有符号的指数(如果有的话)。

它将匹配以e或E结尾的字符串,因此可能是您的验证部分。

详细说明:

^< =行首(而不是字符串)

([0-9]+)< =任意数字至少一次(第一次捕获)

[.]?< =一个小点0或1次(我更喜欢使用转义语法的[。]语法进行阅读

([0-9]+|)< =小数部分或没有(第二次捕获)

(?:[eE]{1}([+-]{0,1}[0-9]+|)|)< =很多部分,详情:

(?:< =非捕获组的开始

[eE]{1}< = 1 e其余的大写或小写

([+-]{0,1}[0-9]+|)< =第三个捕获组,指数是否签名或没有指定(匹配将E添加到您的字符串中)

)< =未捕获组的结束

$行尾