web-dev-qa-db-fra.com

Recherche de modèles dans les fichiers csv

J'ai File.csv qui ressemble à ceci

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

Je souhaite rechercher des modèles, les enregistrer dans un autre fichier journal file.log et les supprimer du premier fichier. Perl ou grep idéalement

  • par exemple, si x + 1 = x2, dans la plage 3, supprimez la ligne et enregistrez son existence dans un autre fichier et son emplacement. Donc, alors 2,4,5,25,11 sera supprimé de file.csv et dans file.log, je trouverais quelque chose comme row 7: 2,3,4,25,11 was removed from file.csv. J'essaie de trouver des séquences
5
Lynob

Si nous interprétons votre exigence comme signifiant que la valeur du troisième champ (colonne) doit être supérieure de un à celle du deuxième champ (colonne), alors avec awk vous pouvez faire des choses comme

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

qui créera votre file.log comme spécifié et écrira les lignes restantes dans newfile.csv. Vous pouvez renommer newfile.csv en file.csv après pour simuler la suppression.

5
steeldriver

Je pense que vous avez besoin d'un langage de programmation plus lourd pour cela. Python est mon langage de choix . Voici donc un script simple avec un exemple simple de test:

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

Ce n'est évidemment qu'un exemple squelette de tests, mais il devrait être utilisable. En cours d’exécution normale, seules les lignes qui ne correspondent pas à STDOUT et celles correspondant à STDERR seront affichées. Cela le rend utile pour rediriger vers un nouveau fichier.

Ici c'est en action:

$ 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

Une fois que vous avez chargé des motifs, vous pouvez simplement passer le csv: python patterns.py input.csv


En termes de performances, Python n'est pas toujours le plus rapide. I utilisez-le parce que c'est assez rapide pour le développement Web et que le temps nécessaire pour écrire est beaucoup plus rapide (ce qui me coûte temps/argent) .

Vous pouvez accélérer les choses avec PyPy. Ceci est une alternative Python runtime qui teste étonnamment bien . Vous n'avez peut-être pas besoin de la version PPA (Trusty est la version 2.2, PPA est la 2.3.1), mais voici comment procéder:

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

Vous lanceriez ensuite votre script avec pypy script.py ou, si vous l'exécutez, changez directement le Shebang d'ouverture en #!/usr/bin/env pypy. J'ai fait quelques très tests simples sur un fichier d'entrée de 350000 lignes (votre exemple répété 50000 fois ) avec ce qui précède scénario.

python2 l'a exécuté en 1.417s et pypy en 0.645s. D'après mon expérience, vous constaterez probablement une amélioration encore plus importante avec des algues plus complexes.

... Mais oui, rien de tout cela ne va battre l'équivalent C/C++. Si le temps que cela prend est de l'argent, passez un peu de temps à le réimplémenter dans un langage plus rapide.

6
Oli

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
2
glenn jackman