Procurando por padrões em arquivos csv

5

Eu tenho file.csv parecido com isso

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

Eu quero encontrar alguns padrões e salvá-los em outro arquivo de log file.log e removê-los do primeiro arquivo. Perl ou grep idealmente

  • por exemplo, se x + 1 = x2, no intervalo de 3, remova a linha e registre sua existência em outro arquivo e onde existiu. Então, 2,4,5,25,11 será removido de file.csv e, em file.log , encontrarei algo como row 7: 2,3,4,25,11 was removed from file.csv . Estou tentando encontrar seqüências
por Lynob 08.08.2014 / 15:31

3 respostas

5

Se interpretarmos sua exigência como significando que o valor do terceiro campo (coluna) deve ser um a mais do que o do segundo campo (coluna), então com awk você pode fazer coisas como

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

que criará seu file.log conforme especificado e gravará as linhas restantes em newfile.csv . Você pode renomear newfile.csv para file.csv depois para simular a exclusão.

    
por steeldriver 08.08.2014 / 16:37
6

Eu acho que você precisa de uma linguagem de programação mais pesada para isso. Python é a minha linguagem de escolha, então aqui está um script simples com um exemplo simples de teste:

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

Isso é obviamente apenas um exemplo esquelético de testes, mas deve ser utilizável. Corra normalmente, ele irá mostrar apenas as linhas que não correspondem ao STDOUT e as que fazem ao STDERR. Isso é útil para redirecionar para um novo arquivo.

Aqui está em ação:

$ 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

Depois de carregá-lo com padrões, basta passar o csv: python patterns.py input.csv

Em termos de desempenho, o Python nem sempre é o mais rápido. Eu uso porque é mais do que rápido o suficiente para o desenvolvimento da web e o tempo para escrever é muito mais rápido (que é o que me custa tempo / dinheiro).

Você pode acelerar as coisas com o PyPy. Este é um tempo de execução alternativo do Python que pontos de referência surpreendentemente bem . Você pode não precisar da versão do PPA (Trusty ships 2.2, PPA é 2.3.1), mas aqui está como você faria:

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

Você lançaria seu script com pypy script.py ou, se estiver executando, altere diretamente a abertura para #!/usr/bin/env pypy . Eu fiz alguns testes muito simples em um arquivo de entrada de linha 350000 (seu exemplo repetido 50000 vezes). a>) com o script acima.

python2 executou em 1.417s e pypy executou em 0.645s . Na minha experiência, você provavelmente verá uma melhora ainda maior com algos mais complicados.

... Mas sim, nada disso vai bater o equivalente C / C ++. Se o tempo de execução for dinheiro, passe algum tempo reimplementando-o em um idioma mais rápido.

    
por Oli 08.08.2014 / 16:08
2

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
    
por glenn jackman 08.08.2014 / 17:43