2

我有一个 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"不是我想要的。(注意逗号后面的空格现在消失了)。

什么是适当的表达来修剪逗号前后的空白,但保留引用的文本不变?

更新

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

4

5 回答 5

2

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

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

替换为空字符串。

这些人的答案假设引号是平衡的,并使用计数来确定空格是否是引用值的一部分。

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

RegexHero 演示

于 2013-10-21T16:03:19.393 回答
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
于 2013-10-21T15:54:48.100 回答
1

这样的事情可能会完成这项工作:

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

[\t ]*,[ \t]*仅当前面没有奇数个引号时才匹配。

于 2013-10-21T15:56:19.660 回答
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);
        }

如果您之间有正确关闭的引号字符串,这将起作用

于 2013-10-21T15:50:36.800 回答
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

于 2013-10-21T17:06:42.803 回答