以前曾问过,但没有解决办法对我有效。
我有一个类似的csv文件:
data1,data2,data3,"<tag field1=""test"" field2=""test,2,3""></tag>",data4
当我用逗号分割时,由于标记中的数据,它不适合,所以我想在每次看到“”时使用正则表达式或其他东西。
我正在使用winforms,我想从csv中只提取data1,data2等。
请问任何想法?
谢谢
编辑:我会更精确:它不应该是一项艰巨的任务,因为我知道我想忽略“标签”中的任何内容,所以正则表达式可以做到这一点吗? 在上面的例子中,我想使用正则表达式并操纵该行给出以下结果:
data1,data2,data3,data4
现在很清楚了吗?谢谢大家
答案 0 :(得分:1)
有几种开源CSV解析器可用作NuGet包,它们将为您处理所有这些。你最好的选择就是使用其中之一,因为没有必要在流行的平台上编写常见文件格式的解析器,因为可能已经有至少一个可以做你想要的了。
如果你真的想自己解析这个问题,除非你真的对解析感兴趣或者你需要一些非常奇特的要求,否则我不会推荐你解决这个问题,你需要一些比简单更有能力的东西。正则表达式。正则表达式不擅长处理引用的字段,您还必须记住,引用的字段可以根据RFC在其中添加换行符。
答案 1 :(得分:0)
如果您在评论时不想使用库,则可以对单行数据(伪代码)执行类似的操作:
read a line
bool bInsideQuotes = false
loop over chars
if character == '"'
bInsideQuotes = !bInsideQuotes
if character == ',' and !bInsideQuotes
found a field separator
或者不是逐行阅读,而是可以阅读整个文件并自行处理换行符(仅当!bInsideQuotes
允许多行行时)。
答案 2 :(得分:0)
出于好奇,我花了大部分时间尝试编写自己的CSV解析器,该解析器可以处理在CSV字段值中输入的逗号和引号的任何变体。这就是我想出的(需要输入字符串$ myfilename和boolean $ use_headers作为输入)
<?php
$rows = file($myfilename)
for($i = 0; $i < count($rows); $i++)
{
# Remove non-printable characters
$rows[$i] = preg_replace('/[[:^print:]]/', '', $rows[$i]);
# Reduce csv line to only commas and quotes
$cleanup_1 = preg_replace('/[^,"]/', '', $rows[$i]);
# Count the number of quote characters between commas.
# When the cumulative number of quotes is an even number,
# you have a distinct field from your CSV line data.
# Record the key valus for delimiter commas.
$delimiters = array();
$count = 0;
foreach(explode(',', $cleanup_1) as $key => $value)
{
$count += strlen($value);
if($count % 2 == 0)
{
$delimiters[] = $key;
$count = 0;
}
}
# Split your original line data by commas and combine
# text values between delimiters.
$strings = array();
$new_array = array();
foreach(explode(',', $rows[$i]) as $key => $value)
{
$strings[] = $value;
if(in_array($key, $delimiters))
{
$text = implode(',', $strings);
# If the field value contains escaped commas or quotes,
# remove the beginning and end quotation marks.
if(substr($text, 0, 1) == '"' && substr($text, strlen($text)-1, 1) == '"')
{
$text = substr($text, 1, strlen($text)-2);
$text = str_replace('""', '"', $text);
}
$new_array[] = $text;
$strings = array();
}
}
# Optional setting to include headers. $user_headers
# will be a boolean input. Result is a set of
# associative arrays with matching, aligned keys.
if($i == 0 && $use_headers)
{
$headers = array();
foreach($new_array as $key => $header)
{$headers[$key] = $header;}
} else {
$tmp = array();
foreach($new_array as $key => $value)
{
if($use_headers)
{$tmp[$headers[$key]] = $value;}
else
{$tmp[] = $value;}
}
$data_array[] = $tmp;
}
}
?>