Text Munger (ou nem tudo é como deveria ser)
por Walter Cruz on 30/06/2008
in Python, Ruby, Geek life
Tudo começou quando eu esbarrei nesse link . O texto contém 15 exercícios de programação, entre eles o que eu me propus a fazer, o text munger.
O exercício consiste no seguinte: dado um texto qualquer, o text munger deve retornar o texto com as palavras desse texto modificadas da seguinte forma: ao invés da palavra original, teremos a primeira letra da palavra original, o resto da palavra (com exceção da última letra) embaralhado seguido da última letra da palavra.
Dentre as várias soluções disponíveis no ruby quiz, a solução em destaque, de Gordon Thiesfeld, usa a expressão regular \b para dividir as palavras. Expressões regulares são iguais em qualquer linguagem, certo? Bom, quase certo. O b funciona da mesma forma no ruby, perl e php, mas funciona de forma diferente no python. Ou não funciona. Na verdade, não sei se é um bug da implementação ou algo assim.
Eu poderia usar outra regex para dividir as palavras e as pontuações, mas já que o fato do \b não funcionar tinha me deixado frustrado com as regex (e eu não queria pensar muito nelas, pra mim o \b deveria funcionar), parti para outra solução. Descobri o shlex, um analisador léxico simples, que para o que eu precisava, funcionava muito bem.
Minha solução para o problema:
import sys
import shlex
from random import shuffle
def munge(text):
t = shlex.shlex(text, posix=False)
t.quotes = "'"
s = [munge_word(word) for word in t]
print(" ".join(s))
def munge_word(aword):
s = list(aword)
first = s.pop(0)
try:
last = s.pop()
except IndexError:
return aword
shuffle(s)
return first + ''.join(s) + last
try:
s = open(sys.argv[1]).read()
munge(s)
except IndexError:
print("Usage: munge.py file")
Observe que a solução não está 100% igual a proposta em ruby. Devido a junção em (" ".join(s)), acabam aparecendo uns espaços em branco que não existiam no texto original.
Existe ainda uma solução em smalltalk proposta pelo Rodrigo Cacilhas no kodumaro. E você gosta de exercícios assim? Sabe porque o \b na implementação de regex do python não funciona como eu esperava? (ou serão minhas expectativas que estão erradas?). Os comentários estão aí para vocês!
Subscribe: 



Não é um bug, você provavelmente não utilizou string literals ao escrever sua regex, ou seja, fez:
re.compile('\b')
ao invés de:
re.compile(r'\b')
Isso porque \b em uma string normal em Python corresponde ao caractere Backspace (ASCII valor 8). Para funcionar como separador de palavras na regex ele deve ser colocado em uma string literal, para não ser interpretado pelo Python.
E sim, string literals em Python existem principalmente para uso com Regex :P
Oi LKRaider! Eu bem queria que eu tivesse cometido um erro básico assim, mas não foi o que aconteceu ;) O \b do python não divide como no php, ruby, ou perl.
Apesar de o \b não funcionar, é possível utilizar (\W+) para obter o mesmo resultado. Fiz alguns testes e acabei de postar no meu blog, depois passa lá.
Abraços
Insônia novamente
Apesar de estar morrendo de cansaço, não consigo dormir. Já li, já escutei música, já fiquei no escuro. Nada. Então resolvi vir para o computador, esperar o sono chegar e enquanto navegava por aí, encontrei este post, do Walter Cruz, falando so...
Olá Walter!
Para medir o tempo utilizei o módulo "hotshot" :)
Abraços!
Bacana! Você se incomodaria de testar a versão que eu acabei de postar? Ou de me mandar os textos que você usou pra eu testar aqui?