我有一个巨大的 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]
的任何单个字符,并且将匹配不是大写字母的任何单个字符。因此匹配除逗号之外的任何单个字符。c
d
e
f
[^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
,如果是则打印该行。