Category Archives: Python

Tanti decimali, il caso di PI

1986_stamp_83d40m_Athena_Recentemente Ok, panico ha partecipato al Carnevale della Matematica tenuto dall’ottimo GLF :-)
Uno scoop: il carnevale porta pochissime visite, appena visibili se si vanno a cercare ma devi metterci molta cura. Forse perché l’argomento era difficile, troppo teorico? Ma io ho partecipato anche con l’altro blog, quello più generalista, il Tamburo Riparato. Di là era per pubblicizzare Linux, risultati molto scarsi, un flop.
Ma l’argomento m’interessa, anzi lo script originale lo rivelo solo oggi.
E non finisce qui: ho altra roba già in bozza, mica posso buttarla :roll:

Ecco la versione naïf per calcolare PI con tante cifre decimali quanto volete. Usa sympy e non è ottimale, anzi: è lentissimissima:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, sympy

ndec = int(sys.argv[1]) + 2
# evalf restituisce il numero di cifre,
#compreso il 3 e il punto  iniziale

pi_str = str(sympy.pi.evalf(ndec))
print pi_str

pisym

OK, le ultime cifre non sono attendibili, come si vedrà in seguito. Inoltre è lentissimo; vediamo cosa capita per un caso più sostanzioso, 1 milione di decimali:

pitime

No, non può andare 10 minuti e 32 secondi! Ma quando il gioco si fa :oops: già detto, cancello.

Un sito da prendere in considerazione in questi casi è Rosetta. Sì, c’è il nostro caso, qui.

#!/usr/bin/python
# -*- coding: utf-8 -*-

def calcPi():
    q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
    while True:
        if 4*q+r-t < n*t:
            yield n
            nr = 10*(r-n*t)
            n  = ((10*(3*q+r))//t)-10*n
            q  *= 10
            r  = nr
        else:
            nr = (2*q+r)*l
            nn = (q*(7*k)+2+(r*l))//(t*l)
            q  *= k
            t  *= l
            l  += 2
            k += 1
            n  = nn
            r  = nr

import sys

ndec = int(sys.argv[1]) + 1
pi_digits = calcPi()

i = 0
for d in pi_digits:
    sys.stdout.write(str(d))
    i += 1
    if i == ndec: print; sys.exit(0)

rosetta1

scrive il 3 iniziale, problema minore. Per quanto riguarda la velocità c’è sempre di mezzo il print, per velocizzare si potrebbe mettere in una stringa (problema aggiuntivoo: in Python le stringhe sono immutabili). In ogni caso ecco:

rotime

Niente, l’ho interrotto, dopo 200 minuti. Cosa succede se tolgo l’output commentando la riga 30? Continua a essere molto lento. Mistero, per adesso meglio la mia versione naïf :shock:
Però, che razza di codice! Chissà da dove viene? Ecco, entrano in gioco la Wiki e Google e prima di subito la soluzione:

OK, ma: 1) non è in Python e 2) Haskell? di nuovo?

Beh, Haskell forse in futuro, per Python c’è Laszlo Szathmary: Digits of PI (Part 2).

Non so se l’argomento interessa solo me; in ogni caso conto di parlarne ancora.
Ah! intanto ho scoperto che c’è un clone FOSS di Mathematica, scritto in Python; interessa? a me sì ovviamente.
Prossimamente… forse… :roll:

IPython

While it does not provide any computational or data analytic tools by itself, IPython is designed from the ground up to maximize your productivity in both interactive computing and software development. It encourages an execute-explore workflow instead of the typical edit-compile-run workflow of many other programming languages. It also provides very tight integration with the operating system’s shell and file system. Since much of data analysis coding involves exploration, trial and error, and iteration, IPython will, in almost all cases, help you get the job done faster.

IPy_header

Me ne avevano già parlato in tanti (sul Web) ma l’ho installato solo oggi. E pensare che… OK, ricomincio dall’inizio.

L’ho installato da terminale sudo apt-get install ipython, scarica ben 3MB sull’hard disk ed è pronto:

ip0

Da provare prima di subito:

ip1

OK. Il sito di IPython dice che la versione corrente (stabile) è la 1.2.1 – February 2014. Con Ubuntu viene installata la 0.13.2, anche se si usa sudo apt-get install ipython-notebook come consigliato dalla docmentazione ufficiale (pagina Installing IPython del sito, in realtà installa la versione per il browser) o da Software Center. Chissà se ad aprile, con Trusty Tahr (che sarebbe poi la Fidata Capra dell’Himalaya (pensa te che i francesi non sono ancora riusciti a cambiargli il nome)) si aggiornerà, vedremo.
Anche il manuale in versione PDF non è aggiornato e io ormai li leggo sul Kindle, scollegato.

OK, vediamo:

ip2

Comodo l’autocompletamento!

def f(x, y, z):
    return (x + y) / z

a = 5
b = 6
c = 7.0

result = f(a, b, c)

ip3

Non ci sono ancora arrivato del tutto ma se si ha uno script (t.py nel mio caso) si può valutare (si capisce valutare o è da lisperato perso) con %run. Con %who si ha l’elenco delle variabili, non so se sia possbile modificarle, tipo debug.

Però…
Sto barando. Finora ho copiato. Devo studiare. Io intanto mi leggo il manuale, l’ho appena caricato sul Kindle poi ne riparlo.
Prossimamente :shock: Forse :roll:

Python vs. Perl

Programming-republic-of-perlSono in ritardo su tutto; devo ancora finire due cose per domani ma devo proprio dire una cosa. Anche perché riguarda in qualche misura quello che devo fare per domani.
Perl, devo essere stato uno dei primi a affrontarlo, è nato nel 1987, controllato anche sulla Wiki, non è un errore, credevo prima. No, non ho prove, anche i libri non li ho più. OK, nostalgia mode OFF :shock:

Oggi ho trovato questo post: The Fall Of Perl, The Web’s Most Promising Language.
L’autore, Conor Myhrvold, è –come dire– eclettico. Ma conosce bene la materia il post è informato e esaustivo.

camelMa il motivo vero di queste note è un altro, anzi più di uno.

Python
Oggi le cose in cui Perl eccelleva si fanno con Python; anche le espressioni regolari. E Python ha un grosso vantaggio: la sintassi è molto più amichevole, sembra il Basic di una volta. E anche la storia dell’indentazione (non è che devo dire rientri, vero?) ho visto che è facile da digerire. E Python è molto usato, ci sono librerie (OK, non si chiamano così ma sono quello che una volta si sarebbero chiamate librerie). Metti in conto che non devi compilare e anzi puoi modificare al volo lo script e Python vince alla grande, ad esclusione dei progetti più impegnativi dove si usa Java o il C++. A proposito non so se è una cosa locale ma il C++ ha fama di essere ostico e impegnativo; io trovo tale anche Java, ma chissà :oops:

Octave (Matlab)
Conor dice che Python “even expanding at Matlab’s expense“. Però, per quel che ne so, Matlab è usato parecchio per calcoli di matrici e roba simile; e ha gli stessi vantaggi di scripting di Python. Resta da verificare se serva la versione proprietaria o sia sufficiente Octave, FOSS.

awk
Ci sono però dei casi in cui forse Python ha dei rivali. Per esempio gli script di awk di cui ho parlato nei post precedenti. Funzionano, anzi cresceranno in futuro. Anche se c’è il problema di Windows.

OK, a proposito per domani devo vedere se usare awk (o Perl) o Python. Scelta difficile io sono pythonista convinto ma vengo da sh, sed, awk e Perl.
E una delle cose di cui vado orgoglioso tra quelle recenti è fatta con Gnuplot :roll:

pass in Python

geek

Il post precedente su continue ha generato un commento che mi sembra il caso di sviluppare. Anche perché voglio enunciare esplicitamente una cosa del blog –dei miei post– che è sempre rimasta tra le cose non dette.

Anche se sono fuori dal mondo del lavoro ogni tanto vedo un vecchio (ma molto più giovane di me) amico con cui si parla anche di programmazione. Niente di eccezionale, anzi l’opposto: non si usa il C/C++, troppo complesso o almeno intimidatorio. Per le cose grosse si usa Java, che secondo me è incasinato come il C++ (o quasi). Io ho proposto Go che mi sembra abbordabile ma forse è troppo nuovo. Poi adesso si è iniziato a usare Octave (e forse Matlab) come fanno al Poli. Un linguaggio, anzi tutto un ambiente, il Visual Basic, usatissimo in passato mi sembra un po’ abbandonato, anche perché limitato a Windows. Per le cose normali adesso si usa Python, anche se ci sono cose che ancora non vanno come si vorrebbe. Ma è comodissimo per i piccoli script, mai più di un centinaio di righe. OK, a volte ci sono moduli importati, e poi il numero di righe non conta, vale la bontà dell’algoritmo.

La programmazione è in ogni caso vista come un mezzo, quello che interessa è trovare il risultato di una procedura, di una simulazione. Caso limite ma reale è quello di ottenere un fattore di sicurezza (pare si chiami davvero così) partendo da una massa di dati enorme ed eterogenea. Dove –importante– conta molto più l’operatore che non la macchina e il programma che c’è dentro.
Inoltre un programma (nel nostro caso si dovrebbe parlare di script) è sempre in beta, si modifica al volo quando si rende necessario. E spesso diventa ingestibile, ma questo sarebbe un altro discorso.
C’è un responsabile ma non è detto che sia l’autore dello script. E nessuno legge come dovrebbe i manuali. Anche perché non è necessario sapere tutto e poi manca il tempo.
Le soluzioni eleganti, classi e metodi razionali, come insegnano la scuola e i libri sono spesso sconosciute. Avete presente gli if kilometrici e le variabili globali? OK, se funziona va bene.

Poi, e vengo al dunque, Python ci mette del suo. Come fa notare Roberto nel commento al post citato si potrebbe usare pass:

pass is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, but no code needs to be executed.

Lo script di ieri diventa così:

#!/usr/bin/python
# -*- coding: utf-8 -*-

n = 0
while n < 6:
	n += 1
	c = n % 3
	if c == 0:
		pass
	elif c == 1:
		print n, c, "*"
	else:
		print n, "**"
print "OK!"

pass

Risultato identico a quello dello script di ieri. In realtà l’unica differenza e la sostituzione di continue con pass.

Ci sono differenze tra le due istruzioni? Ho googlato, cercato in Stack Overflow ma non ho trovato niente; forse devo cercare meglio, o forse qualcuno che ne sa di più ci dirà.
Io personalmente ho sempre usato continue (e il suo fratello break) all’interno dei cicli e pass nella gestione delle eccezioni.
A proposito: con gli ing. di cui sopra mai parlare di errori, è una parolaccia :mrgreen:


Poi ogni tanto faccio anche dei post diversi, per esempio ne sto preparando uno che…
prossimamente :cool:

Aggiornamento

al3hex nel commento ha risolto il mistero. Che mistero non era ovviamente :roll:

continue in Python

Una storiella ma forse può essere utile per qualcuno. Questa è capitata per via della standardizzazione: “d’ora in poi tutto in Python (e Java e Octave e …)“. Inoltre a peggiorare le cose c’era il capo che continuava a girare nei paraggi, in questi casi sapete come ci si deve comportare, vero?

geek

Il codice era più complesso, questo è solo un esempio semplificato al massimo.

#!/usr/bin/python
# -*- coding: utf-8 -*-

n = 0
while n < 6:
	n += 1
	c = n % 3
	if c == 0:
		print n, "###"
	elif c == 1:
		print n, c, "*"
	else:
		print n, "**"
print "OK!"

0

In Python non esiste l’istruzione switch o case o cond, solo l’if. Quindi l’esempio è corretto, e funziona.

Però salta fuori che bisogna fare una modifica: nel caso in cui c vale 0 non bisogna far nulla.
Il geek ha modificato il codice così (prudentemente ha commentato anziché cancellare l’istruzione divenuta inutile):

#!/usr/bin/python
# -*- coding: utf-8 -*-

n = 0
while n < 6:
	n += 1
	c = n % 3
	if c == 0:
		#print n, "###"
	elif c == 1:
		print n, c, "*"
	else:
		print n, "**"
print "OK!"

1

Ops! non funziona, Python vuole qualcosa da fare, anche quando vogliamo non faccia nulla.

C’era il capo che girava e allora ecco la soluzione:

#!/usr/bin/python
# -*- coding: utf-8 -*-

n = 0
while n < 6:
	n += 1
	c = n % 3
	if c == 0:
		#print n, "###"
		k = 1
	elif c == 1:
		print n, c, "*"
	else:
		print n, "**"
print "OK!"

2

Sì, inserire un’istruzione qualunque dove Python la vuole, funziona, il capo queste cose non le guarda, caso risolto.

Però, secondo me, non vale. C’è il manuale online, dai, prova a cercare “continue“, c’è in altri linguaggi e fa proprio quello che vogliamo:

continue may only occur syntactically nested in a for or while loop, but not nested in a function or class definition or finally clause within that loop. It continues with the next cycle of the nearest enclosing loop.

Verifica:

#!/usr/bin/python
# -*- coding: utf-8 -*-

n = 0
while n < 6:
	n += 1
	c = n % 3
	if c == 0:
		continue
	elif c == 1:
		print n, c, "*"
	else:
		print n, "**"
print "OK!"

3

OK! Questa può essere intesa come la versione 2014 di “e leggere quel *bip* di manuale!:roll:

Il conto torna

Alla TV francese danno un programma TV che si intitola Des chiffres et des lettres in cui i concorrenti si sfidano a risolvere sia giochi di parole che di aritmetica. Uno dei giochini si intitola Le compte est bon: vengono dati alcuni numeri, e un numero obiettivo, e lo scopo è di ottenere l’obiettivo (o avvicinarcisi il più possibile) applicando le quattro operazioni aritmetiche alla serie di iniziale numeri.

Per capire di cosa si tratta, facciamo subito un piccolo esempio: dati i numeri 5, 100, 6, 3, 10 e 1, bisogna cercare di ottenere il numero 635 utilizzando soltanto le quattro operazioni +, -, * e /.

Una possibile sequenza che porta alla soluzione è:

5+100 = 105; 6*105 = 630; 3-1 = 2; 10/2 = 5; 630+5 = 635;

Come vedete, non è poi molto difficile, ma bisogna perderci un attimo di tempo a provare un po’ di combinazioni.

Viene fuori che la maestra di mio figlio, che frequenta la CM2 (quinta elementare) qui in Francia, propone questo tipo di esercizi per allenare i ragazzini a fare i conti. Divertente, no? Non l’avevo mai visto fare in Italia, ma può darsi che mi sbagli, se seguite questo blog e ne sapete di più sugli esercizi che vengono dati in quinta elementare in Italia, scrivetelo nei commenti! A questo sito trovare parecchi esercizi simili per tutte le classi delle elementari.

Fatto sta che qualche giorno fa, mio figlio si presenta con questa sequenza: 1, 2, 5, 10, 25, 50, e il numero da ottenere era 668. Non riusciva a trovare la soluzione, e voleva sapere se potevo trovarla io.

Dopo averci pensato qualche secondo, gli ho detto che secondo me non c’era soluzione. “Forse ho sbagliato a copiare qualche numero”, mi risponde lui, “ma mi sembrava di aver ricopiato attentamente dalla lavagna”.

Come sapere se c’è o no soluzione al problema? Beh, da buon ingegnere, ho pensato che il modo migliore era di scrivere un programmino che provasse tutte le combinazioni. Con 5 numeri non dovrebbero essere tantissime. Ovviamente, essendo un problema semplice, il modo veloce di risolverlo era usare il Python, il mio lignuaggio di fast-prototyping preferito ormai.

Volete provarci da soli? Allora non guardate il programma seguente.

import copy
import argparse

numeri = [5, 100, 6, 3, 10, 1]
soluzione = 635

def elimina(i, lista):
    l = []
    l = copy.copy(lista[:i])
    l = l + copy.copy(lista[(i+1):])
    return l


def operazione(lista, sol, ops, ris, operazione, a, b):
    l3 = copy.copy(lista)
    l3.append(ris)
    op = ops + str(a) + operazione + str(b) + ' = ' + str(ris) + '; '
    calcola(l3, sol, op)


def calcola(lista, sol, ops):
    if len(lista) == 1:
        if lista[0] == sol:
            print "TROVATO! ", ops
    else:
        n = lista[0]
        l = elimina(0, lista)
        for i, x in enumerate(l):
            l2 = elimina(i, l)

            n1 = n + x
            operazione(l2, sol, ops, n1, '+', n, x)

            n1 = n - x
            operazione(l2, sol, ops, n1, '-', n, x)

            n1 = x - n
            operazione(l2, sol, ops, n1, '-', x, n)

            n1 = n * x
            operazione(l2, sol, ops, n1, '*', n, x)

            if x != 0 and n % x == 0:
                n1 = n / x
                operazione(l2, sol, ops, n1, '/', n, x)

            if n != 0 and x % n == 0:
                n1 = x / n
                operazione(l2, sol, ops, n1, '/', x, n)


def main():
    parser = argparse.ArgumentParser(description='Inserisci i numeri')
    parser.add_argument('nums', nargs='+', default=numeri)
    parser.add_argument('--s', default=soluzione)

    args = parser.parse_args()
    num = [int(x) for x in args.nums]
    sol = int(args.s)

    print num, ' ??? ', sol
    calcola(num, sol, "")


if __name__ == "__main__":
    main()

E lanciando il programma si ottengono… ben 2 risultati!

[1, 2, 5, 10, 25, 50]  ???  668
TROVATO!  10-1 = 9; 2+5 = 7; 25+50 = 75; 9*75 = 675; 675-7 = 668; 
TROVATO!  1-25 = -24; 2+5 = 7; 10*50 = 500; -24*7 = -168; 500--168 = 668; 
TROVATO!  25-1 = 24; 2+5 = 7; 10*50 = 500; 24*7 = 168; 500+168 = 668; 

La seconda in realtà coinvolge dei numeri negativi, quindi andrebbe eliminata. E quindi aveva ragione mio figlio e torto io. Mai contare troppo sulle proprie doti matematiche!

Il programma l’ho scritto un po’ di fretta e non è il massimo dello stile, e non sono neanche completamente sicuro che sia corretto. E quindi, per chi volesse esercitarsi, ho tre domande a diverso grado di difficoltà:

  • Sapete modificare il programma per evitare che stampi soluzioni negative?
  • E se voleste memorizzarle tutte le soluzioni in un vettore per riutilizzarle dopo?
  • Infine, sapete dimostrarne la correttezza?

Dimenticavo: ovviamente, un programma analogo è disponibile in linea qui.

Ah, questi francesi!

Modificare il testo – III

re3Non so voi ma io resto del parere che le RE sono una brutta bestia. Da trattare con le dovute precauzioni, come detto nel post precedente.
A proposito ho provato a rifare lo script pdx.py usando replace(), metodo delle stringhe, ma dopo un po’ ho deciso che non è una via percorribile, in particolare per sostituire la virgola all’interno dei numeri reali scritti in italiano. Mi sono arreso (forse troppo presto, magari ci riproverò) anche a rifare lo script in newLISP, il mio linguaggio di scripting preferito. Ma non ho capito cosa non va nella RE (\d)[,](\d) eppure sembra tanto semplice. Mistero (almeno per ora).

Lo script pdx.py l’ho testato e sembra tutto OK. Cosa succede se il file di dati fosse grande (decisamente più grande di quelli per cui è stato scritto)? Di seguito procedo a un test con un file finto, testuale anziché numerico.
Il file dei dati contiene i primi due capitoli di Pinocchio, in formato testuale, scaricato da Liber Liber.

p0

Lo script viene modificato per il test in questo modo:

  • cerca le v e w e le sostituisce con *, in luogo di punto-virgola e tab;
  • cerca le u all’interno di una parola e le sostituisce con #, in luogo della virgola all’interno del numero.
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

txt = re.sub(r'(\S)[u](\S)', r'\1*\2', re.sub('[vw]', '#', txt))
print txt

p1

Verifico, per la coppia v e w si ha:

p2

mentre per la u ottengo:

p3

Chiaramente il conteggio a righe non è precisissimo, ma c’è meld:

click per ingrandire

click per ingrandire

Sì sembra OK.

Consumo di risorse:

p5

decisamente trascurabile, quasi invisibile.

p6

e istantaneo.

OK, fatto :roll:

Modificare il testo – II

regexOK, mi è stato fatto notare che lo script precedente, quello che sostituisce il punto-virgola e il tab con uno spazio manca ancora di una funzione indispensabile per le vecchie versioni di M$ Office: sostituire la virgola con il punto nei numeri reali o float (o come li chiamate voi, quelli non interi, insomma).

loPerò, forse c’è un modo semplice e veloce: io uso Libre Office e quando salvo come CSV mi chiede come:

csv0

e

csv1

Comunque sì, si può modificare lo script. Notare che la virgola dev’essere sostituita solo all’interno di un espressione numerica, anche se questi file di dati in genere le hanno solo con quella funzione. Ho costruito e utilizzo un nuovo file di dati (finti): d2.xls:

d2

La riga 4 si riferisce a date, usando non so bene che formato che non bisogna usare.
Ed ecco lo script aggiornato (pdx.py):

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

txt = re.sub(r'(\d)[,](\d)', r'\1.\2', re.sub('[;\t]', ' ', txt))
print txt

pdx

Altra cosa dimenticata: esiste un’ampia letteratura sulle RE, io ho usato principalmente Regular Expression HOWTO, c’è quasi tutto quello che serve. Inoltre mi trovo sempre più spesso a vagare dalle parti di Stack Overflow, a mia insaputa :roll:

In questo periodo mi sto occupando di altre cose (non trascuro il blog anche se qualcuno potrebbe avere quell’impressione) ma prossimamente voglio provare una soluzione alternativa, usando replace() e non le RE. E confrontarle in termini di efficienza.
Prossimamente, forse… :mrgreen:

Filter con Python

filterUna cosa urgente (!) a completamento del post precedente. Quando c’è un’emergenza eccomi! E se poi la richiesta fosse comparsa sul blog (ci sono i commenti apposta per quello) sarebbe ancora meglio.

Domanda:
In Linux ci sono parecchi comandi che leggono da tastiera e scrivono sul monitor, tipo echo:

0

Si può fare una cosa simile con Python?

Risposta:
Cerrrto!
Questi comandi si chiamano filtri. “In Unix and Unix-like operating systems, a filter is a program that gets most of its data from its standard input (the main input stream) and writes its main results to its standard output (the main output stream). Unix filters are often used as elements of pipelines. [...] Common Unix filter programs are: cat, cut, grep, head, sort, uniq, and tail.dice la Wiki. Sì c’è anche in italiano ma la versione inglese mi piace di più.
E per farlo con Python c’è già tutto online, su Stack Overflow.

#!/usr/bin/python
<pre># -*- coding: utf-8 -*-

import sys

for line in sys.stdin:
    sys.stdout.write(line)

1

D: Ma non si vede la differenza da prima, con echo liscio!

R: Sì ma se ti metto una pipe, così:

2

e dopo puoi fare anche questo:

3

Ecco, filtri archiviati (credo) :roll:

Modificare il testo con Python

re

Le espressioni regolari –d’ora in poi RE– non è che sono semplicissime. Vanno prese a piccole dosi, quasi omeopatiche come nel post precedente.

Oggi vediamo di riscrivere gli script con un linguaggio serio, Python. Non che io non consideri serio newLISP ma ho visto che il solo nominarlo fa venire l’orticaria alla gente.

Prossimamente affronteremo più razionalmente le RE ma per adesso tutto quello che ci serve è sapere che c’è il modulo re di cui utilizzeremo i metodi compile() e sost().

Ecco dpv.py, lo script per sostituire i punti-virgola son spazi:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

p = re.compile(';')
print p.sub(' ', txt)

0

Si potrebbe trattare in modo simile il file con i dati separati da tab, basta modificare la riga 15, sostituendo ; con \t.

Però possiamo fare un passo in più: scrivere la RE che trovi (come si dice match, no, non fiammifero) sia il punto-virgola che il tab, ecco dsost.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys, os, re

if len(sys.argv) < 2:
	print "uso: ", sys.argv[0], "file-dei-dati"
	sys.exit(2)
if not os.path.isfile(sys.argv[1]):
	print "manca il file ", sys.argv[1]
	sys.exit(2)

txt = open(sys.argv[1], 'r').read()

p = re.compile(';|\t') # qui!
print p.sub(' ', txt)

1

Sì, rispetto allo script precedente cambia solo la riga 15.

E, non so come la pensate voi ma secondo me, le RE non sono poi così perverse. C’è gente che le maneggia continuamente, i perlisti :roll:

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Unisciti agli altri 71 follower