我正在处理一些非常格式不正确的日志文件,列分隔符是(通常)出现在字段中且不是的项目逃过一劫。例如:
sam,male,september,brown,blue,i like cats, and i like dogs
其中:
name,gender,month,hair,eyes,about
正如您所看到的,about包含列分隔符,这意味着分隔符的单个分析将不起作用,因为它会将about me分成两个单独的列。现在用聊天系统想象一下......你可以想象出我确定的问题。
那么,理论上解决这个问题的最佳方法是什么?我不是在寻找特定于语言的实现,而是更多关于正确方向的一般指针,或者关于其他人如何解决它的一些想法...... 没有手动完成它。
编辑:
我应该澄清,我的实际日志处于更糟糕的状态。这些字段到处都有分隔符,没有我可以找到的模式。
答案 0 :(得分:4)
如果只有最后一列有未转义的逗号,那么大多数语言的字符串拆分实现可以限制分割的数量,例如:在Python s.split(',',5)
如果要将文件解析为CSV(逗号分隔值)解析器,那么我认为最好的方法是运行一个在将其传递给csv解析器之前进行正确转义的修复程序。
答案 1 :(得分:3)
我想你可以对数据类型做出某些假设。与gender
一样,month
,hair
和eyes
都有一个值域,然后验证。
除about
和name
之外的所有字段都不包含逗号也可能有意义,所以也许你可以贪婪地解析使前5或6个逗号表现为分隔符和所有内容else是about
的一部分。如有必要,请再次验证。
答案 2 :(得分:2)
如果没有使用转义,可能无法完美地解析它们。
Lie Ryan指出,如果只有最后一列可以有这些值,那么你可以选择。
如果不是这样的话,是否有任何一栏确保您始终缺少未转义的保留字符?此外,是否有任何列保证您始终只有一组特定值?
如果其中任何一个属实,您可以先识别这些字段,然后将其他所有字段分开,将其从那里拆分。
我必须了解有关您的信息的更多细节,以便更进一步。
答案 3 :(得分:1)
以下是您可以尝试的两个想法:
长度/格式模式 - 我认为您可以识别文件各列中的某些模式。例如,某些列中的值可能更短,某些列中的值可能更短。某些列中的值通常是数字或来自有限的一组值(例如,几个月)或至少包含一些子字符串。
当您可以识别这些模式时(基于从项目正确提交的项目计算的统计数据),您应该创建使用这些模式的算法来猜测应忽略哪些分隔符(例如,当列比预期短时)
语法规则 - 受你的例子启发的另一个想法 - 是没有转义的逗号,通常后跟一些字符串(例如单词“and”或“about”?)如果是,您可以使用此信息来猜测哪些delmiters应该被转义。
最后,如果这些临时技术都不能解决您的问题,那么您可以使用一些繁重的统计数据来进行估算。有一些机器学习框架可以为你做大量统计,但它仍然是相当复杂的问题。例如,在.NET上,您可以使用Microsoft Research的{{3}}。
答案 4 :(得分:0)
我建议做的一件事,如果可能的话,就是在每个数据记录中保留一些内容,表明所做的假设(可能保留原始字符串),这样如果发现记录中的某些内容有正确的数据希望可以重建(如果没有别的话,可以通过手工检查)。
答案 5 :(得分:0)
如果第6列始终是最后一列,并且始终没有转义,那么这个perl应该可以解决这个问题:
$file = '/path/to/my/log.txt';
open(LOG, $file);
@lines = <LOG>;
foreach $line (@lines)
{
chomp($line);
if ($line =~ /([A-Za-z0-9_]+)\,([A-Za-z0-9_]+)\,([A-Za-z0-9_]+)\,([A-Za-z0-9_]+)\,([A-Za-z0-9_]+)\,([A-Za-z0-9_\, ]+)/)
{
print "Name: $1\n";
print "Gender: $2\n";
print "Month: $3\n";
print "Color #1: $4\n";
print "Color #2: $5\n";
print "Random Text: $6\n";
}
}
close(LOG)
答案 6 :(得分:0)
您的日志含糊不清:您无法确定要做出多种可能的解释。处理不确定性是概率论的一项工作。一个自然的工具是probabilistic context-free grammar - 有一些算法可以找到最可能的解析。 (我没有机会自己使用一个,虽然我用这种统计方法完成了更简单的工作.Peter Norvig的spelling-corrector article详细介绍了一个这样的例子。)
对于这个特殊的简化问题:你可以列举所有可能的方法将一条线分成N个部分(你已经知道了N的期望),根据某个模型计算每个部分的概率,并选择最佳答案。
(处理删除区别的数据的另一个例子:我有一个来自50万Flickr照片的标签数据集。标签来自他们的API,所有的单词和空格都被压缩了。我计算的最有可能使用从互联网摄影网站制表的字频率的字边界,加上this SO answer等代码。)