在csv文件中搜索模式

我有file.csv看起来像这样

4,6,18,23,26 5,12,19,29,31 2,5,13,16,30 9,10,24,27,32 4,5,10,19,22 4,6,8,10,25 2,3,4,25,11 

我想找到一些模式,并将它们保存在另一个日志文件file.log ,并从第一个文件中删除它们。 理想的Perl或grep

  • 例如,如果x + 1 = x2,在3的范围内,则删除该行并将其存在于另一个文件中以及它存在的位置。 那么2,4,5,25,11将从file.csv2,4,5,25,11中删除我会发现像row 7: 2,3,4,25,11 was removed from file.csv 。 我正在努力寻找序列

如果我们将您的要求解释为意味着第三个字段(列)的值应该比第二个字段(列)的值多一个,那么使用awk可以执行类似的操作

 awk -F, ' $3==$2+1 {print "row "NR": "$0" was removed from "FILENAME > "file.log"; next}1 ' file.csv > newfile.csv 

这将按指定的方式创建您的newfile.csv并将剩余的行写入newfile.csv 。 您可以在模拟删除file.csv重命名为file.csv

我认为你需要一个更重的编程语言。 Python是选择的语言,所以这是一个简单的脚本,带有一个简单的测试示例:

 import sys tests = [ lambda a, b, c, d, e: a+1==b and b+1==c and c+1==d and d+1==e, ] with open(sys.argv[1]) as f: for line in f: if any(t(*map(int, line.split(','))) for t in tests): sys.stderr.write('Line removed: %s\n' % line) continue print line 

这显然只是测试的骨架示例,但它应该可用。 正常运行它将只输出与STDOUT不匹配的行以及对STDERR执行的行。 这使得重定向到新文件很有用。

这是在行动:

 $ python patterns.py <(echo -n 1,2,3,4,5) Line removed: 1,2,3,4,5 $ python patterns.py <(echo -n 1,2,4,4,5) 1,2,4,4,5 

一旦你用模式加载它,你就可以将它传递给csv: python patterns.py input.csv


在性能方面,Python并不总是最快的。 使用它是因为它对于Web开发而言足够快,而且编写时间要快得多(这就是我花费时间/金钱的时间)。

你可以用PyPy加快速度。 这是一个替代Python运行时,其基准测试非常好 。 你可能不需要PPA版本(Trusty发货2.2,PPA是2.3.1)但是你会这样:

 sudo add-apt-repository ppa:pypy/ppa sudo apt-get update sudo apt-get install pypy 

然后,您将使用pypy script.py启动脚本,或者如果您正在执行它,请将开放的shebang更改为#!/usr/bin/env pypy 。 我用上面的脚本对350000行输入文件(你的例子重复50000次 )进行了一些非常简单的测试。

python2pypy运行它, 0.645s在0.645s运行它。 根据我的经验,你可能会看到更复杂的算法更大的改进。

......但是,这些都不会超过C / C ++等价物。 如果运行所花费的时间是金钱,花一些时间用更快的语言重新实现它。

perl的:

 $ perl -i.bak -F, -ane ' if ($F[0]+1 == $F[1] and $F[1]+1 == $F[2]) {warn "row $.: $_"} else {print} ' file.csv 2>file.log $ cat file.log row 7: 2,3,4,25,11 $ cat file.csv 4,6,18,23,26 5,12,19,29,31 2,5,13,16,30 9,10,24,27,32 4,5,10,19,22 4,6,8,10,25