正则表达式删除逗号周围的空格,除非引用

时间:2013-10-21 15:25:33

标签: c# .net regex csv replace

我有一个CSV文件,其行类似于:

1,  4,     2, "PUBLIC, JOHN Q" ,ACTIVE , 1332

我正在寻找一个与这些行匹配的正则表达式替换,并吐出类似这样的东西:

1,4,2,"PUBLIC, JOHN Q",ACTIVE,1332

我认为这很容易:我创建了表达式([ \t]+,)并将其替换为,。我做了一个补充表达式(,[ \t]+),替换了,,我认为我已经取得了良好的右边修剪和左边修剪的方法。

...但后来我注意到我的"PUBLIC, JOHN Q"现在是"PUBLIC,JOHN Q",这不是我想要的。 (注意逗号后面的空格现在已经消失了。)

在逗号之前和之后修剪空格的适当表达式是什么,但保留引用文本不变?

更新

为了澄清,我正在使用一个应用程序来处理该文件。这个应用程序允许我定义多个正则表达式替换;它不提供解析功能。虽然这可能不是理想的机制,但它肯定会为这个文件制作另一个应用程序。

5 个答案:

答案 0 :(得分:2)

如果您的工具使用的引擎是C#正则表达式引擎,那么您可以尝试以下表达式:

(?<!,\s*"(?:[^\\"]|\\")*)\s+(?!(?:[^\\"]|\\")*"\s*,)

替换为空字符串。

这些家伙的答案假设报价是平衡的,并使用计数来确定空间是否是引用值的一部分。

我的表达式查找不属于引用值的所有空格。

RegexHero Demo

答案 1 :(得分:1)

使用一些CSV库或自己解析文件会更容易,而IMO应该是更好的选择。

但如果你真的坚持使用正则表达式,你可以使用这个:

"\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"

并将其替换为空字符串 - ""

此正则表达式匹配一个或多个空格,后跟偶数引号。这当然只有在你有平衡的报价时才有效。

(?x)       # Ignore Whitespace
\s+        # One or more whitespace characters       
(?=        # Followed by 
   (          # A group - This group captures even number of quotes
     [^\"]*     # Zero or more non-quote characters
     \"         # A quote
     [^\"]*     # Zero or more non-quote characters
     \"         # A quote 
   )*         # Zero or more repetition of previous group
   [^\"]*     # Zero or more non-quote characters
   $          # Till the end
)          # Look-ahead end

答案 2 :(得分:1)

这样的事情可能会起到作用:

(?<!(^[^"]*"[^"]*(("[^"]*){2})*))[\t ]*,[ \t]*

哪个匹配[\t ]*,[ \t]*,只有在没有前面有奇数引号的情况下才会匹配。

答案 3 :(得分:0)

        string format(string val)
        {
            if (val.StartsWith("\"")) val = " " + val;
            string[] vals = val.Split('\"');
            for (int i = 0; i < vals.Length; i += 2) vals[i] = vals[i].Replace(" ", "").Replace("\t", "");
            return string.Join("\t", vals);
        }

如果您在

之间正确关闭了引用的字符串,这将有效

答案 4 :(得分:0)

忘记正则表达式(参见Bart对该问题的评论,正则表达式不适合CSV)。

public static string ReduceSpaces( string input )
{
    char[] a = input.ToCharArray();
    int placeComma = 0, placeOther = 0;
    bool inQuotes = false;
    bool followedComma = true;
    foreach( char c in a ) {
        inQuotes ^= (c == '\"');
        if (c == ' ') {
            if (!followedComma)
                a[placeOther++] = c;
        }
        else if (c == ',') {
            a[placeComma++] = c;
            placeOther = placeComma;
            followedComma = true;
        }
        else {
            a[placeOther++] = c;
            placeComma = placeOther;
            followedComma = false;
        }
    }
    return new String(a, 0, placeComma);
}

演示:http://ideone.com/NEKm09