Python + grep per un db selvaggio

Tanto tempo fa, nell’altro millennio, quando non esistevano ancora i telefoni cellulari, mi ero fatto uno script molto semplice che attraverso grep trovava il numero di telefono della persona che cercavo.
Nella sua forma più elementare dato il file di testo elenco composto da righe nome numero basta il comando grep -ih nome elenco. L’opzione i dice di ignorare le differenze tra maiuscole e minuscole, come si usa nel mondo DOS/Windoze, la h dice di non stampare il nome del file. Funziona ma si può abbellire, cosa che è stata fatta N+1 volte.
Poi il prof (*) Lipari raccontando dei suoi trascorsi mi ha fatto conoscere Bjoern B. Brandenburg. Che è un geek davvero eccezionale. E nelle sue pagine sul sito di UNC c’è un sacco di roba.
E anche se le sue pagine non sono molto aggiornate (ma dice che quando avrà tempo lo farà) ho trovato, tra l’altro una Simple Grep Shell che, grazie anche a Python, fa scintille; io l’ho adottata, così com’è, ma poi l’ho anche usata per far compiere un balzo gigantesco al mio script.
E questa è la mia versione:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# da Bjoern B. Brandenburg

import sys
import os
import readline
from termcolor import colored

HISTFILE   = 'qsh_history'

EGREP      = 'grep'
STD_ARGS   = ['-ihP', '--color']

class HistFile(object):
    def __init__(self, file):
        self.histfile = os.path.join(
            os.path.abspath(os.path.dirname(sys.argv[0])), file)
        try:
            readline.read_history_file(self.histfile)
        except IOError:
            pass

    def store(self):
        try:
            readline.write_history_file(self.histfile)
        except IOError:
            pass

def grep(pattern):
    args = [EGREP]
    args.append(pattern)
    args.extend(STD_ARGS)
    args.append('ele-tel') # qui i files dei dati
    args.append('int-tel')
    args.append('/dev/null')
    return os.spawnvp(os.P_WAIT, EGREP, args)
    # sarebbe meglio usare subprocess, prossimamente

block_ch = lambda col: colored(u'\u2588', col)

def main(args):
    history = HistFile(HISTFILE)
    try:
        while True:
            print block_ch('cyan') * 20
            pattern = raw_input('-> ')
            if pattern != '':
                try:
                    pattern = '.*'.join(pattern.split())
                    grep(pattern)
                except KeyboardInterrupt:
                    pass
    except (EOFError, KeyboardInterrupt):
        print 'Bye.'
    history.store()

if __name__ == '__main__':
    main(sys.argv)

Allora dati i files “del database” ele-tel

Piero ufficio 3456
Piero lab 7773
Piero officina 1022
Piero de Rossi 3223
Piero Derossi 3009
Piero de' Rossi 3223
Gianpiero 1222
Giorgio Rossi 1992
Piergiorgio Rossi 1990
Françoise 5555
Francoise 5556
Francesca 5557
Renée 5600
Rene' 5700
Müller, Hans 4200
Adams, Douglas N. 4242

e int-tel

lab centralino 7001
portone accesso 1001
sicurezza 1099
beppe 9911

otteniamo:

dove si vede che funziona benissimo, non è necessario ricorrere alle espressioni regolari, funziona con le lettere accentate e esotiche. Dipende com’è fatto il file dei dati: nella versione indicata va bene per lo stile dei Carabinieri — cognome nome 😉

L’unica cosa mia è la sostituzione degli spazi con la regex.*‘ per cui si possono saltare i caratteri esotici (ü e ç negli esempi) mettendo uno spazio.
Il ctrl-D per uscire credo sia abbastanza standard per la/lo shell.

Lo script usa il modulo termcolor (riga 8, ne ho parlato qui) per visualizzare una linea di separazione tra una ricerca e l’altra. Se si vuole si può ometterla togliendo la riga # 46: print block_ch('cyan') * 20.

Confessione
Ho detto una piccola bugia nel senso che non lo uso per i numeri di telefono ma per altre informazioni che variano piuttosto rapidamente (giornalmente). Funziona alla grande: che grep sia eficiente non è certo una novità per nessuno.
Gli script per costruire il file dei dati sono piuttosto banali e, allo stato attuale, una schifezza. Prossimamente…
Anche lo script Python illustrato potrebbe essere migliorato: usare il nuovo modulo subprocess e ordinare alfabeticamente i risultati, prossimamente, forse.

(*) prof se preferisci posso indicare alla ‘merikana dr, fammi sapere.

Posta un commento o usa questo indirizzo per il trackback.

Commenti

  • glipari  Il 14 ottobre 2010 alle 14:34

    Bello questo, quando vedo Bjorn (a dicembre) glielo dico!
    Chiamami pure come ti pare, “prof”, “doc”, “ehi tu”, per me va sempre bene!

    (sto scrivendo slides come un pazzo, prima o poi ve ne metto qualcuno qui sopra)

  • seo adelaide  Il 4 giugno 2013 alle 02:20

    It’s hard to come by well-informed people for this subject, however, you seem like you know what you’re talking about!
    Thanks

Lascia un commento

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.