仅保留包含确切数量的分隔符的行

仅保留包含确切数量的分隔符的行

我有一个巨大的 csv 文件,其中有 10 个字段,用逗号分隔。不幸的是,有些行格式错误,并且不包含正好 10 个逗号(当我想将文件读入 R 时,这会导致一些问题)。如何过滤掉恰好包含 10 个逗号的行?

答案1

另一个 POSIX:

awk -F , 'NF == 11' <file

如果该行有 10 个逗号,则该行将有 11 个字段。所以我们简单地awk使用,作为字段分隔符。如果字段数为 11,则条件NF == 11为 true,awk则执行默认操作print $0

答案2

使用egrep(或grep -E在 POSIX 中):

egrep "^([^,]*,){10}[^,]*$" file.csv

这会过滤掉任何不包含 10 个逗号的内容:它匹配整行(^在开头和$结尾),包含{10}序列“任意数量的字符(除了 ',',后跟单个 ','”)的十次重复 ( ) ( ([^,]*,)),后跟除“,”( [^,]*) 之外的任意数量的字符。

您还可以使用该-x参数来删除锚点:

grep -xE "([^,]*,){10}[^,]*" file.csv

这比效率低库恩勒姆awk解决方案;在我的系统上,对于包含 10 个左右逗号的行,后者通常要快六倍。更长的线路会导致速度大幅下降。

答案3

最简单的grep代码可以工作:

grep -xE '([^,]*,){10}[^,]*'

解释:

-x确保模式必须匹配全部的线,而不仅仅是其中的一部分。这很重要,因此不要匹配包含超过 10 个逗号的行。

-E表示“扩展正则表达式”,这可以减少正则表达式中的反斜杠转义。

括号用于分组,after{10}表示括号内的模式的一行中必须恰好有十个匹配项。

[^,]是一个字符类,例如,将匹配 a 、 a 、 an或 an[c-f]的任何单个字符,并且将匹配不是大写字母的任何单个字符。因此匹配除逗号之外的任何单个字符。cdef[^A-Z][^,]

*字符类后面的意思是“零个或多个这些” 。

因此,正则表达式部分的([^,]*,)意思是“除逗号之外的任何字符出现任意次数(包括零次),后跟一个逗号”,并且{10}指定了 10 个这样的字符。然后[^,]*将其余的非逗号字符匹配到行尾。

答案4

抛出一些简短的python

#!/usr/bin/env python2
with open('file.csv') as f:
    print '\n'.join(line for line in f if line.count(',') == 10)

这将读取每一行并检查该行中的逗号数量是否等于 10 line.count(',') == 10,如果是则打印该行。

相关内容