在 csv 文件中搜索模式

Lyn*_*nob 5 grep perl csv text-processing

我有看起来像这样的 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
Run Code Online (Sandbox Code Playgroud)

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

  • 例如,如果 x+1 = x2,在 3 的范围内,删除该行并记录它在另一个文件中的存在以及它存在的位置。所以然后2,4,5,25,11将被删除file.csv,在 file.log我会找到类似的东西row 7: 2,3,4,25,11 was removed from file.csv。我试图找到序列

Oli*_*Oli 6

我认为你需要一种更重的编程语言。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
Run Code Online (Sandbox Code Playgroud)

这显然只是测试的一个骨架示例,但它应该是可用的。正常运行它只会输出与 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
Run Code Online (Sandbox Code Playgroud)

一旦你用模式加载了它,你就可以将它传递给 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
Run Code Online (Sandbox Code Playgroud)

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

python2在 1.417 秒内pypy运行它并在0.645s. 根据我的经验,使用更复杂的算法,您可能会看到更大的改进。

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


ste*_*ver 5

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

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

这将创建您file.log指定的并将剩余的行写入newfile.csv. 您可以重命名newfile.csvfile.csvafter 以模拟删除。