除非分隔符被转义,否则使用分隔符分割
我正在阅读来自Excel使用的剪贴板数据
var stream = (System.IO.Stream) ( Forms.Clipboard.GetDataObject() ).GetData( Forms.DataFormats.CommaSeparatedValue );
,
但不幸的是,excel传递单元格文本而不是单元格值。 当单元格使用特殊的格式(如千分位数)时,剪贴板中的一系列单元格的数据如下所示:
1,234,123.00 2,345.00 342.00 12,345.00
存储为:
\" 1,234,123.00 \",\" 2,345.00 \", 342.00 ,\" 12,345.00 \"
当我真正想要的是这样的:
1234123.00, 2345.00, 342.00, 12345.00
我以前曾经使用clipData.Split(new string[] { "," }, StringSllitOptions.None))
函数将我的CSV剪贴板数据转换为一系列单元格,但是当包含逗号的格式化文本转义失败时,将失败。
我问是否有人可以想办法将这个string拆分成一组单元格,而忽略在\"
位\"
内转义的逗号,因为这是Excelselect转义包含逗号的单元格的方式。
总之,我怎样才能把一个单一的string包含这个:
\" 1,234,123.00 \",\" 2,345.00 \", 342.00 ,\" 12,345.00 \"
转换为包含以下内容的string数组:
{ "1,234,123.00", "2,345.00", "342.00", "12,345.00" }
不破坏我的能力,parsing一个简单的逗号分隔的string。
*****编辑***
后续问题(制定为DFA): 每次确定性有限自动机达到最终状态时分割一个string?
首先,我已经处理了Excel中的数据,而且通常看到的是逗号分隔的值,如果该值被认为是一个string,则会在其周围有双引号(可以包含逗号和双引号)。 如果它被认为是数字,那么没有双引号。 此外,如果数据包含一个双引号,将由双引号分隔""
。 所以假设所有这些是我过去如何处理的
public static IEnumerable<string> SplitExcelRow(this string value) { value = value.Replace("\"\"", """); bool quoted = false; int currStartIndex = 0; for (int i = 0; i < value.Length; i++) { char currChar = value[i]; if (currChar == '"') { quoted = !quoted; } else if (currChar == ',') { if (!quoted) { yield return value.Substring(currStartIndex, i - currStartIndex) .Trim() .Replace("\"","") .Replace(""","\""); currStartIndex = i + 1; } } } yield return value.Substring(currStartIndex, value.Length - currStartIndex) .Trim() .Replace("\"", "") .Replace(""", "\""); }
当然,这里假定数据是有效的,所以如果你有类似于"fo,o"b,ar","bar""foo"
这是行不通的,另外如果你的数据包含了"
一个“可能会或可能不会是可取的。
有很多方法可以做到这一点。 一个不起眼的方法是:
- 转换\“,\”到选项卡或其他分隔符(我假设你在你的例子中省略了一些“,否则string是不一致的
- 剥去所有剩余的逗号
- 剥去所有剩下的“
- 将您的分隔符(例如制表符)转换回逗号
现在,你有第一个你想要的东西
我同意凯尔关于你的string可能不一致。
而不是凯尔的第一步,你可以使用
string[] vals = Regex.Split(value, @"\s*\"",\s*");
从您的input示例中,我们可以看到有三个“不需要”的字符序列:
\" \", ,\"
因此,将所有这些序列添加到Split
方法的input数组中:
string[] result = clipData.Split(new[] { @",\""", @"\"",", @"\""" }, StringSplitOptions.None);
这会给你一个包含几个空元素的数组。 如果这是一个问题,请使用StringSplitOptions.RemoveEmptyEntries
而不是StringSplitOptions.None
:
string[] result = clipData.Split(new[] { @",\""", @"\"",", @"\""" }, StringSplitOptions.RemoveEmptyEntries);
你可以尝试使用一点LINQ:
string excelData = "\\\" 1,234,123.00 \\\",\\\" 2,345.00 \\\", 342.00 ,\\\" 12,345.00 \\\""; IEnumerable<string> cells = from x in excelData.Split(new string[] { "\\\"" }, StringSplitOptions.RemoveEmptyEntries) let y = x.Trim(',').Trim() where !string.IsNullOrWhiteSpace(y) select y;
或者,如果您不喜欢此build议,请尝试使用RegEx实现类似的模式。