否定字符类匹配字符序列

问题描述:

我有点问题,因为我是一个正则表达式新手。如果它很重要,我使用.NET的Regex类。否定字符类匹配字符序列

首先我使用正则表达式中的数据的描述:

这里是我的表达:

(".*[^".]);(.*")

这这两条线相匹配(他们是从较大的行的一部分在电脑主机一台,但基本上将是这个样子):

例1:7906143476.;180.;903.;1.;1970.;8.;42.;1.;327.;"SST9001";"S;T GORANS SJH "

实施例2:2.;"1;AVD INGENJOR ";"N";"J";" ";

而且也能够匹配这个(我想它不是没有匹配):

;"U";33.75;777.;" ";

正则表达式的含义是找到所有分号(;)内引号(“)并用冒号(:)代替。在引号前后不一定总是有分号(如例1)。我想输出是:

7906143476.;180.;903.;1.;1970.;8.;42.;1.;327.;"SST9001";"S:T GORANS SJH "

2.;"1:AVD INGENJOR ";"N";"J";" ";

最后一行应保持不变,因为它有一个点和分号之前的任何数量的数字()。

我希望能够用一个正则表达式匹配所有这些可能的行。我已经有了多个正则表达式的解决方案,但我想要一个更好的方式来做到这一点。我不太了解负面/积极的前瞻/背后,但我有一种感觉,那就是解决方案在这个领域的某个地方。

我首先想到的是在否定角色类内部组合一个旁边,这样我就可以否定0.75,这是我不想匹配的第一组$ 1。它可以是任何数字,而不是75。

任何帮助都会很棒,因为我对正则表达式根本不擅长。

谢谢!

所以,换句话说,只有当分号是引用字符串的一部分时,才需要用分号替换分号?

假设引号是正确的平衡,不存在引用的字符串(如"2\" by 4\"")中存在的报价,那么你可以这样做:

resultString = Regex.Replace(subjectString, 
    @";   # Match a ; 
    (?=   # if it's followed by an odd number of ; -- namely: 
    [^""\r\n]* # 0+ non-quote, non-linebreak characters 
    ""   # One quote 
    (?:   # followed by... 
     [^""\r\n]*"" # an even number of non-quote-quote sequences 
     [^""\r\n]*"" 
    )*   # zero or more times 
    [^""\r\n]* # followed by zero or more non-quotes 
    $    # until the end of the line. 
    )    # End of lookahead", 
    ":", RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace); 
+0

谢谢,作品魅力!需要阅读我认为的Friedl书。 此外,感谢您提供有关代码的出色评论,非常适合帮助理解。 – 2011-03-25 15:12:39

+0

是你确定,它工作吗?..我已经测试过与拉德正则表达式设计器http://www.radsoftware.com.au/regexdesigner/,它不工作.. – 2011-03-25 15:18:29

+0

是啊,每次工作对我来说,什么字符串是你用?测试? – 2011-03-25 15:25:19

另一种建议:在';'上分割,然后遍历数组,如果当前字符串以“但不结尾”开始,则用下一个带有':'的字符串连接它,继续直到找到结尾'''或到达数组末尾

用';'连接所有元素。并打印。

顺便说一句,'''不能逃脱?这对于所有解决方案都会使问题变得复杂。

+0

我想过这个选项,但它似乎更清洁,通过正则表达式来做。引号总是出现在甚至数字,并永远不会逃脱,所以这不会是一个问题,谢谢你ugh =) – 2011-03-25 15:10:55

检查这个表达式:

(?<=("[^"]*";)|([^"];)+)"[^"]*[;][^"]*" 

它匹配中有至少一个分号引号之间的任何东西,但只,如果是由其他引号或东西是没有加东西之前。这避免了你的问题,我用你提供的字符串进行了检查。

"[^";\n]*?(;)*?[^";\n]*?“,没有任何环视construct..Its性能应该比其他建议的解决方案更好..你要做的只是用冒号替换组1 \1 ..