Arquivo da tag: regex

Dump email addresses from files

Suppose you have a lot of .doc, .docx, .xls, .xlsx, .gz, .bz2, .pdf and text in general (.csv, .txt etc.) files and want to dump all the (unique) email addresses from them. How would you do it? Here is a simple solution I’ve just implemented (and probably didn’t test enough, so tell me if you find any bug):

#!/bin/sh
tmp=$(tempfile)
while [ $# -gt 0 ]; do
    if [ -r "$1" ]; then
        ext=$(echo ${1#*.} | tr [A-Z] [a-z])
        case $ext in
            docx | xlsx)
                # requires: http://blog.kiddaland.net/2009/07/antiword-for-office-2007/
                cat_open_xml "$1" >> $tmp
                ;;
            doc)
                # requires: antiword
                antiword "$1" >> $tmp
                ;;
            xls)
                # requires: catdoc
                xls2csv "$1" >> $tmp
                ;;
            gz)
                cat "$1" | gunzip >> $tmp
                ;;
            bz2)
                cat "$1" | bunzip2 >> $tmp
                ;;
            zip)
                unzip -p "$1" >> $tmp
                ;;
            pdf)
                # requires: xpdf-utils
                t=$(tempfile)
                pdftotext "$1" $t
                cat $t >> $tmp
                rm $t
                ;;
            *)
                text=$(file -b --mime-type "$1" | sed -e 's//.*//')
                if [ "z$text" = "ztext" ]; then
                    cat "$1" >> $tmp
                fi
                ;;
        esac
    fi
    shift
done
cat $tmp | grep -o -E '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}\b' 
         | tr [A-Z] [a-z] | sort -u
rm $tmp

(the email regexp is explained here: regular-expressions.info/email.html)

Compras e Blog

ATENÇÃO: Este conteúdo foi publicado há 11 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Hoje, no Linuxmall, comprei um pequeno livro chamado Invasão de Redes: Ataques e Defesas e foi escrito por Tiago José Pereira Nogueira. Nunca vi nada desse cara, ninguém me recomendou esse livro e não conheço ninguém que já tenha lido ou comentado alguma coisa sobre ele. É um livro que parece ser novo e me deu vontade de comprar porque sempre quis saber trabalhar com redes no C. Ele aborda tópicos interessantes, como sockets e conexões, port scanners, DDoS, entre outras coisas. Só tô explicando pra vocês não pensarem que eu comprei porque decidi virar um cracker maligno invasor de redes… :lol: Aproveitei o frete pra comprar também um novo adesivo pro laptop, um Tux grande (de 11x13cm – eu medi antes pra ver se ficava legal no laptop) que custou R$ 2,00. A compra deve chegar quinta-feira. A propósito, alguém já ouviu falar de E-Sedex? Parece ser legal… Barato e rápido! Pedi essa compra com ele pra testar. Faz tanto tempo que não compro na internet que eu fico por fora dessas novidades!

Vou aproveitar o post pra postar os códigos que eu estou fazendo pra interpretação de BBCodes e estatísticas do blog que eu, o Hélio e o Gustavo começamos a desenvolver semana passada e queremos acabar até no máximo o final de novembro (pretendemos acabar perto do dia 15/11).

Expressões Regulares

< ?php
/* A parte de regex de códigos precisa do GeSHi Highlighter. Includando-o... */
include("geshi.php");
 
/* Essa classe serve para ser usada com "extends", ela sozinha "não é nada". */
class Regex {
 
    /* Função que interpreta emoticons */
    function Emoticons() {
        $origem=Array(":)", ":(", ":D", ":P", ":O", ":S", ":lol:", ":blink:");
        $destino=Array("feliz.gif", "triste.gif", "sorriso.gif", "lingua.gif", "espantado.gif", "confuso.gif", "riso.gif", "confuso.gif");
        // EM DESENVOLVIMENTO!
    }
 
    /* Função que interpreta BBCodes...
     * Totalmente desenvolvida por mim. (nem parece de tão linda, né?) */
    function InterpretaBBCodes() {
        /* Vamos começar pelos [codes], porque só o que tá fora deles deve ser
           interpretado depois. */
 
        preg_match_all("/[code language=([a-z]+)](.*)[/code]/sU", $this->texto, $matches_com_linguagens);
        preg_match_all("/[code](.*)[/code]/sU", $this->texto, $matches_sem_linguagens);
 
        /* - A parte dos códigos é $matches_com_linguagens[$i][2] e $matches_sem_linguages[$i][1].
               - A parte que diz em que linguagem os códigos $matches_com_linguagens[$i][2] foi escrita
              é $matches_com_linguagens[$i][1].
           - Para facilitar os códigos abaixo, vou trocar matches_com_linguagens para mcl e
           matches_sem_linguagens para msl. Só não fiz em cima pra quem tá de fora entender o que
           eu tô fazendo nessa parte do código. ;)
        */
 
        $mcl=$matches_com_linguagens;
        $msl=$matches_sem_linguagens;
 
        $con=0;
        for ($i=0; $i<sizeof ($mcl[0]); $i++) {
            $g=new GeSHi($mcl[2][$i], $mcl[1][$i], "./geshi/");
            $geshi_mcl[$i]=$g->parse_code();
            $mcl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($mcl[0][$i], $mcl_md5[$i], $this->texto);
        }
        for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
            /* Aqui, vocês vão perguntar: "Por que passar no GeSHi, se não sei highlightear essa linguagem?
               A resposta é que o GeSHi não só highlighta, mas formata o código de forma que ele fique
               legível (por exemplo, troca < por &lt. */
            $g=new GeSHi($msl[1][$i], "", "./geshi/");
            $geshi_msl[$i]=$g->parse_code();
            $msl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($msl[0][$i], $msl_md5[$i], $this->texto);
        }
 
        /* Beleza, agora precisamos sempre lembrar de não highlightear o que estiver entre <pre>.
           E também não podemos deixar nada fora dos padrões XHTML Strict. */
 
        $this->texto=str_replace("&", "&amp;", $this->texto);
        $this->texto=str_replace("< ", "&lt;", $this->texto);
        $this->texto=str_replace(">", "&gt;", $this->texto);
        $this->texto=str_replace(""", "&quot;", $this->texto);
 
        // Aqui tá o meu "nl2br" semântico! =)
        $this->texto="<p>".$this->texto."</p>";
        $this->texto=preg_replace("/nnn*/", "<p>", $this->texto);
            /* </p><p></p> vazios não são semânticos. Mas estive pensando depois de fazer isso e acho que
                algumas pessoas podem querer dar um grande espaço entre os <p>, por isso estou
                pensando em fazer uma ER que a cada n a mais de dois n's adicione 10px ao
                margin-bottom do último </p><p>. O que vocês acham? */
        $this->texto=preg_replace("/n/", "<br />n", $this->texto);
        $this->texto=preg_replace("/< /p></p><p>/", "</p>n<p>", $this->texto);
 
        // Formatação básica (negrito, itálico, sublinhado, cores, cabeçalhos)
           $this->texto=preg_replace("/[b](.*)[/b]/sU", "<strong>\1</strong>", $this->texto);
        $this->texto=preg_replace("/[i](.*)[/i]/sU", "<em>\1</em>", $this->texto);
        $this->texto=preg_replace("/[u](.*)[/u]/sU", "<span style="text-decoration:underline;">\1</span>", $this->texto);
        $this->texto=preg_replace("/[color=([^]]+)](.*)[/color]/sU", "<span style="color:\1;">\2</span>", $this->texto);
        $this->texto=preg_replace("/[h([1-6])](.*)[/h\1]/sU", "<h \1>\2< /h\1>n", $this->texto);
 
        // Citações
        $this->texto=preg_replace("/[quote](.*)[/quote]/sU", "<q>\1</q>n", $this->texto);
        $this->texto=preg_replace("/[quote=([^]]+)](.*)[/quote]/sU", "<q>\2</q>n<cite>\1</cite>", $this->texto);
 
        // URLs
        $this->texto=preg_replace("/([^"/=]])(www.[^[:blank:]"< ]+)/", "\1<a href="http://\2">\2", $this->texto);
        $this->texto=preg_replace("/([^"=]])(http://[^[:blank:]"< ]+)/", "\1<a href="\2">\2", $this->texto);
 
        $this->texto=preg_replace("/[url]([^"]*)[/url]/sU", "<a href="\1">\1</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^[:blank:]"]+)[[:blank:]]+title=([^]"]+)](.*)[/url]/sU", "<a href="\1" title="\2">\3</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^]"]+)](.*)[/url]/sU", "<a href="\1">\2</a>", $this->texto);
 
 
        preg_match_all("/<a href="([^"]+)">/U", $this->texto, $matches);
 
        for ($i=0; $i<count ($matches[0]); $i++) {
            $parse=parse_url($matches[1][$i]);
            $dominio=$parse["host"];
            $this->texto=str_replace($matches[0][$i], "<a href="".$matches[1][$i]."" title="Link Externo: $dominio">", $this->texto);
        }
 
        // Imagens    
        $this->texto=preg_replace("/[img=([^]]+)]([^"]*)[/img]/U", "<img src="\2" alt="\1" />", $this->texto);
        $this->texto=preg_replace("/[img]([^"]*)[/img]/U", "<img src="\1" alt="Imagem: \2" />", $this->texto);
 
        // Listas
        $this->texto=preg_replace("/[list](.*)[/list]/sU", "<ul>\1</ul>", $this->texto);
        $this->texto=preg_replace("/[li](.*)[/li]/sU", "<li><p>\1</p></li>", $this->texto);
 
        // Limpando besteiras... Alguém tem alguma idéia melhor do que esse FOR feio?
        for ($count=0; $count&lt;10; $count++) {
            $this->texto=preg_replace("/<br />< /li>/", "", $this->texto);
            $this->texto=preg_replace("/<ul><br />/", "</ul><ul>", $this->texto);
            $this->texto=preg_replace("/< (/?)li><br />/", "< \1li>",  $this->texto);
            $this->texto=preg_replace("/<q><br />/", "</q><q>", $this->texto);
            $this->texto=preg_replace("/< /q><br />/", "</q>", $this->texto);
        }
 
        // Emoticons
        // $this->Emoticons();
 
        /* Lembram que o código tinha sido transformado em md5s com o tempo, pros
           bbcodes não entrarem em ação dentro deles? Então vamos transformar de
           volta em códigos agora... */
 
        for ($i=0; $i<sizeof ($mcl[0]); $i++) {
            $this->texto=str_replace($mcl_md5[$i], $geshi_mcl[$i], $this->texto);
        }
 
        for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
            $this->texto=str_replace($msl_md5[$i], $geshi_msl[$i], $this->texto);
        }
 
        // Limpando as besteiras que não precisam ser repetidas (e coloquei depois dos codes porque
        // aqui corrijo o negócio com os <pre>s.
        $this->texto=preg_replace("/<p>[[:blank:]]*<pre>(.*)< /pre>[[:blank:]]*< /p>/sU", "<\/pre><pre>\1<\/pre>", $this->texto);
        $this->texto=preg_replace("/</p><p>[[:blank:]]*<ul>(.*)< /ul>[[:blank:]]*< /p>/sU", "</ul><ul>\1</ul>", $this->texto);
        $this->texto=preg_replace("/</p><p>[[:blank:]]*<h (.)>(.*)< /h\1>[[:blank:]]*< /p>/sU", "</h><h \1>\2</h>", $this->texto);
        $this->texto=preg_replace("/< ([^>]+)>[[:blank:]]?< /\1>/", "", $this->texto);
 
        // E pra finalizar, o mais mala de todos... =)
        $this->texto.="n";
    }
}
?>

Tá bem comentado e queria pedir pra quem puder, dar uma testada com ele (coloquem uns BBCodes errados e coisas que vocês acham que eu não iria prever). Aí embaixo então a parte das estatísticas, para as quais estou usando um pouco do código do Shortstat. Ela tá assim por enquanto:

Estatísticas

< ?php
class Estatisticas {
    var $ip, $pais, $codigopais, $referer, $url, $dominio, $res, $useragent, $navegador, $versaonavegador, $plataforma, $unixtime;
 
    /* Função que descobre o IP real do visitante
     * Copiada de: www.foo.com.br
     */
    function IpReal() {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "desconhecido")) {
            $ip=getenv("HTTP_CLIENT_IP");
        } else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "desconhecido")) {
            $ip=getenv("HTTP_X_FORWARDED_FOR");
        } else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "desconhecido")) {
            $ip=getenv("REMOTE_ADDR");
        } else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "desconhecido")) {
            $ip=$_SERVER['REMOTE_ADDR'];
        } else {
            $ip="desconhecido";
        }
 
        return $ip;
    }
 
    /* Função para descobrir navegador, sistema operacional, etc. com base no User Agent.
     * "SI_parseUserAgent()" do Shortstat, levemente modificada.
     */
    function ParseUserAgent($ua) {
        $plataforma="Desconhecida";
        $navegador="Desconhecido";
        $versao="";
 
        if (eregi("Win", $ua)) {
            $plataforma="Windows";
        } else if (eregi("Mac", $ua)) {
            $plataforma="Macintosh";
        } else if (eregi("Linux", $ua)) {
            $plataforma="Linux";
        } else if (eregi("W3C", $ua)) {
            $plataforma="W3C Validator";
            $navegador="W3C Validator";
            $versao="-";
        } else if (eregi("Googlebot", $ua)) {
            $plataforma="Googlebot";
        } else if (eregi("msnbot", $ua)) {
            $plataforma="MSNBot";
        } else if (eregi("Cynthia", $ua)) {
            $plataforma="Cynthia";
            $navegador="Cynthia";
            $versao="0";
        }
 
        if (eregi("Mozilla/4", $ua)&&!eregi("compatible", $ua)) {
            $navegador="Netscape";
            eregi('Mozilla/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Mozilla/5", $ua)||eregi("Gecko", $ua)) {
            $navegador="Mozilla";
            eregi('rv(:| )([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("Safari", $ua)) {
            $navegador="Safari";
            $plataforma="Macintosh";
            eregi('Safari/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("iCab", $ua)) {
            $navegador="iCab";
            eregi('iCab/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firefox", $ua)) {
            $navegador="Firefox";
            eregi('Firefox/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firebird", $ua)) {
            $navegador="Firebird";
            eregi('Firebird/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Phoenix", $ua)) {
            $navegador="Phoenix";
            eregi('Phoenix/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Camino", $ua)) {
            $navegador="Camino";
            eregi('Camino/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Chimera", $ua)) {
            $navegador="Chimera";
            eregi('Chimera/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Netscape", $ua)) {
            $navegador="Netscape";
            eregi('Netscape[0-9]?/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("MSIE", $ua)) {
            $navegador="Internet Explorer";
            eregi('MSIE ([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Opera", $ua)) {
            $navegador="Opera";
            eregi('Opera( |/)([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("OmniWeb", $ua)) {
            $navegador="OmniWeb";
            eregi('OmniWeb/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Konqueror", $ua)) {
            $navegador="Konqueror";
            $plataforma="Linux";
            eregi('Konqueror/([[:digit:].]+', $ua, $b);
            $versao=$b[1];
        }
        if (eregi('Crawl', $ua) || eregi('bot', $ua) || eregi('slurp', $ua) || eregi('spider', $ua)) {
            $navegador="Crawler/Search Engine";
            $versao="-";
        }
        if (eregi('Lynx', $ua)) {
            $navegador="Lynx";
            eregi('Lynx/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
            $plataforma="Linux";
        }
        if (eregi('Links', $ua)) {
            $navegador="Links";
            eregi('(([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
 
        $array=Array($navegador, $versao, $plataforma);
        return $array;
    }
 
    /* Função para determinar o país do visitante
     * "SI_determineCountry()", do Shortstat, bem modificada por mim.
     */
    function DeterminarPais($ip) {
        global $BASE;
        $ip=sprintf("%u", ip2long($ip));
 
        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("SELECT nome, codigo FROM ".$BASE['TABELA_PAISES']." WHERE ip_from < = $ip AND ip_to >= $ip");
        $array=$db->FetchRow();
 
        $db->Desconecta();
 
        /* Agora um monte de linhas por causa da incompetência do PHP 5.0.5... Hehehe... */
        $tmp1=preg_replace("/([A-ZxC0-xDF])/e", "chr(ord('\1')+32)", $array[0]);
        $tmp2=ucwords($tmp1);
        $array[0]=trim($tmp2);
 
        return $array;
    }
 
    /* Função para "increase stats"
     * O arquivo "inc.stats.php" do Shortstat, bem modificado por mim.
     */
    function IncStats() {
        global $BASE;
        $this->ip=$this->IpReal();
        list($this->pais, $this->codigopais)=$this->DeterminarPais($this->ip);
        $this->referer=$_SERVER["HTTP_REFERER"];
        $this->url=parse_url($this->referer);
        $this->dominio=eregi_replace("^www", "", $this->url["host"]);
        $this->resource=$_SERVER["REQUEST_URI"];
        $this->useragent=$_SERVER["HTTP_USER_AGENT"];
        list($this->navegador, $this->versaonavegador, $this->plataforma)=ParseUserAgent($this->useragent);
        $this->unixtime=time();
 
        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("INSERT INTO ".$BASE['TABELA_ESTATISTICAS']." (ip, pais, codigopais, dominio,
        referer, resource, useragent, plataforma, navegador, versao, unixtime) VALUES ('{$this->ip}',
        '{$this->pais}', '{$this->codigopais}', '{$this->dominio}', '{$this->referer}', '{$this->resource}',
        '{$this->useragent}', '{$this->plataforma}', '{$this->navegador}', '{$this->versaonavegador}',
        '{$this->unixtime}')");
        $db->Desconecta();
    }
}
?>

Bom… Esses dois códigos estão em desenvolvimento ainda, mas acho que com o tempo vão melhorando. Tem umas coisas na parte de Regex que eu queria tornar mais simples mas ainda não descobri como! :blink: Quem quiser sugerir, sinta-se a vontade.

Expressões Regulares no C

ATENÇÃO: Este conteúdo foi publicado há 11 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Sem querer, visitando a página do cara que desenvolve as Funções ZZ com o Aurélio, o Thobias, acabei descobrindo que o C possue uma biblioteca para expressões regulares! Não sei porquê, mas sempre pensei que o C não tivesse esse suporte e nunca parei pra investigar…

Agora descobri que o C tem uma biblioteca chamada regex.h com quatro funções simples para ERs:

       int regcomp(regex_t *preg, const char *regex, int cflags);
       int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
       size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
       void regfree(regex_t *preg)

Não vou aumentar muito esse assunto, mas deixar aqui o link do artigo do Thobias: thobias.org/doc/er_c.html.

A propósito… A página dele é muito legal! Você se sente usando Linux modo-texto… :lol:

E já que falei sobre ERs e Funções ZZ, vou por último falar de um patch que eu fiz pra função ZZCalcula dar as respostas em notação científica e com precisão maior, o que é extremamente importante para eu não precisar ficar contando zeros no novo grupo de estudo de física (que fiz com o prof. Valdir, o Ivo e o John) onde estamos estudando principaplmente astronomia e ter respostas precisas. O patch está disponível aqui e serve para a última versão das ZZ (5.9): Patch para Funções ZZ 5.9, para ZZCalcula resolver as operações com notações científicas e precisão mais alta. Para quem já modificou muito seu arquivo das funções, ou não gosta de patches, publiquei também no meu servidor somente o código inteiro da nova função ZZCalcula com esse recurso: zzcalcula.txt

Hmmm… Eu resolvi começar a floodar mais aqui no blog, isso é, usar a idéia de assuntos diferentes em posts diferentes… Espero que ninguém que recebe e-mails sempre que eu publico uma coisa nova se estresse muito; mas se tiver chato eu dou um jeito de fazer um cron (meu novo servidor tem suporte a cronjobs! E já que eu nunca usei, seria muito legal aprender…) ;)

Novo site do Colégio!

ATENÇÃO: Este conteúdo foi publicado há 11 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Publiquei hoje o novo site do Colégio Salesiano Itajaí, um site totalmente administrável (até o título pode ser mudado via formulários) que usa a linguagem PHP e o banco de dados MySql. O site também segue os padrões web, mesmo com formulários rich text que às vezes deixam o site pouco semântico (é que os monitores do Colégio devem poder atualizar) e está disponível em: salesianoitajai.g12.br.

A notícia de estréia da página está disponível aqui e conta com um lindo screenshot do meu Fluxbox com Mrxvt e o Vim com três splits. Embora o site já esteja publicado, ainda tenho que arrumar alguns detalhes como por exemplo o Sitemap que eu cito nesta notícia.

Uma coisa bem legal que eu coloquei no site foi um JavaScript, usando a função addGlobalStyle do Dive into Greasemonkey, que nos Mozillas (ereg(“Gecko/”, $_SERVER[“HTTP_USER_AGENT”])) faz o site ficar maior se o usuário usar uma resolução igual ou maior a 1024×768. Dá pra fazer pra todos os navegadores, mas eu sou meio newbie em JavaScript e por isso só usei esse código do Greasemonkey, que só funciona nos Mozillas mesmo… Mas o resultado ficou ótimo! :)

Ontem o Sr. Paulo Matias me ensinou como trabalhar com operadores bit-a-bit no C. Achei muito massa! Agora comecei até a economizar fazendo:

numero = outronumero << 1;

… ao invés de simplesmente:

numero = outronumero * 2;

… para meus programas serem mais rápidos! Hehehe :D Fiz uma função que converte de decimal para binário, e depois vou postar aqui.

Observação: Tenho que descobrir porque os emoticons não funcionam quando tem código… Quer dizer, descobrir eu já descobri, mas preciso ver como eu faço pra resolver de forma boa essas expressões regulares…

Editado!

Corrigi o problema… Confira abaixo o novo trecho de ERs da função de emoticons, onde $o é o vetor de origem (com as carinhas originais), $d é o vetor de desgino (com o <img src…) e replace() é uma função que eu criei para substituir os emoticons:

<?php
if (!ereg("<code", $texto)) {
	$texto=replace($o, $d, $texto);
} else {
	preg_match_all("/</code>(.+)<code/sU", $texto, $mat1);
	for ($i=0; $i<sizeof($mat1[1]); $i++) {
		$texto=str_replace($mat1[1][$i], replace($o, $d, $mat1[1][$i]), $texto);
	}
	preg_match("/^(.+)<code/sU", $texto, $mat2);
	$texto=str_replace($mat2[1], replace($o, $d, $mat2[1]), $texto);
	$rev=strrev($texto); //Tenho medo do PHP5.0.5
	preg_match("/^(.+)>edoc/</sU", $rev, $mat3); //Nossa, que código louco!
	$rev=strrev($mat3[1]); //Repito... Tenho medo do PHP5.0.5
	$texto=str_replace($rev, replace($o, $d, $rev), $texto);
}
?>

Ficou feio, né? Não consegui pensar em outra coisa mais fácil que usar o strrev() ali… :blink:

Biologia, Torres de Hanói, Long Double, Mandriva e Expressões Regulares

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Hoje fiz uma prova de biologia. Minha média em biologia estava em 7,93 (8 em um trabalho, 5,8 em uma prova, 10 em participação) e acho que com essa prova vai continuar na mesma, se não piorar. Acredito que eu vá tirar no mínimo 8,5 nessa prova e no máximo 9,5. Pelo menos foi melhor que na outra em que eu tirei 5,8. Bom, só pra não parecer que eu sou burro, minhas notas nas outras matérias nas provas que eu recebi essa semana foram:

  • 10 em inglês
  • 10 em português (e mais 10 numa redação)
  • 10 em matemática
  • 10 em geografia
  • 10 em história
  • 9,5 em química (e mais 10 num trabalho)
  • 9,5 em física

Hmmm… Acho que dá pra perceber que meu problema é biologia mesmo…

Sinceramente, eu odeio essa matéria. Nas outras disciplinas a gente aprende e desenvolve raciocínio lógico. Biologia é só uma decoreba. Não compreendo qual é a utilidade de saber a função das bactérias para nossa vida ou, como um enunciado da prova dizia, “Se você capturasse exemplares de piranhas no Pantanal Mato-grossense, o que você faria pra descobrir de que cadeia alimentar elas fazem parte com base somente nesses exemplares?” Qual a utilidade disso aí? Se eu quisesse ser biólogo até beleza, mas isso aí é inútil. Em matemática, aprendemos coisas úteis. Em biologia, só aprendemos coisas assim… Se ainda fosse como ano passado onde estudávamos atualidades biológicas como células-tronco, AIDS, DSTs, Gripe do Frango, etc., tava ótimo mas esse ano tá um “saco”.

Acho que essa gente que gosta de biologia só pensa no vestibular ao dizer que ela é útil… O básico dela até pode ser útil, mas metade do que a gente aprende na escola de biologia não é útil.

Bom, parando de falar sobre isso… Vamos para as Torres de Hanói

Ontem eu deixei o laptop a noite inteira fazendo as Torres de Hanói com 30 pinos. Utilizando o algoritmo que está implementado em torresdehanoi.c o programa ficou 728 minutos (12 horas) testando e não conseguiu chegar a um fim. Com outros testes, consegui os seguintes tempos:

  • 10 pinos – 0 s
  • 15 pinos – 1 s
  • 20 pinos – 20 s
  • 25 pinos – 20 min
  • 30 pinos – mais de 12 horas

É assombroso a maneira com que vai aumentando…

Bom, utilizando o tipo long double do C eu fiz a conta de 2^64 para ver o custo da “Lenda de Brama” (é esse o nome?)

2^64=18.446.744.073.709.551.616

Ou seja, 18 quinquilhões e meio… Isso é muita coisa.

O interessante é que eu nunca tinha usado o long double com números tão grandes e então fiz alguns testes. Eu cheguei ao resultado de 2^1000, 2^10000 e cheguei a conclusão de que o último número que ele consegue escrever sem dizer que é inf (infinito?) é 2^16383, ou seja, 2^(2^14-1). Saiu umas 40 linhas no console, é muito grande!

Hmmm, demonstrei mais alguns teoremas como a Relação Fundamental da Trigonometria (usando o teorema de Pitágoras – basta dividir os dois lados por a^2), fórmula de Bhaskara, o volume de um cubo inscrito numa esfera pode ser calculado através do raio da esfera, etc. (não lembro de todos). Na verdade, não fui eu que demonstrei. Demonstramos no treino da Olimpíada de Matemática. Eu, o Vavá e o Bruno.

A Mandrakesoft comprou a Conectiva, formando o Mandriva. Eu achei uma pena que uma distribuição importante do Brasil (a primeira) acabou assim. Ela foi muito importante no software livre do Brasil, da América Latina e do mundo. Porém, acredito que a distro Mandriva vai crescer e se popularizar. Quando sair alguma, eu queimo um CD pra testar.

Peguei a música Estrada do Sol (Tom Jobim) no piano (uma versão muito boa escrita por Paulo Jobim e disponível no site www.tomjobim.com.br) e estou pegando Falando de Amor. Assim que der tempo, eu queria gravar algumas músicas que eu toco pra colocar aqui…

Acabei de ler o livro do Aurélio sobre expressões regulares e aprendi bastante coisa interessante. Expressões Regulares são MUITO úteis!

Algoritmo de Permutação e Expressões Regulares

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

permutar (dicionário Priberam)

permutar | v. tr. | v. tr. e int.

Conjugar
do Lat. permutare

v. tr.,
dar reciprocamente;

trocar uma coisa por outra;
cambiar;

v. tr. e int.,
trocar reciprocamente os lugares.

Em matemática, estuda-se a análise combinatória apenas no segundo ano do Ensino Médio (sinceramente, acho isso tão errado quanto não ensinarem a fórmula de Heron ao invés de b.h/2), mas por ser muito útil nas olimpíadas de matemática, acabei aprendendo antes. A permutação que o meu programa faz é com elementos repetidos. Dando a ele um limite de números (naturais) e o número de algarismos de cada saída, ele imprime todas as possibilidades na tela.

Permutação

#include <stdio .h>
 
#define NMAX 101 //Esta é uma constante que define o tamanho do vetor
#define NIVELMAX 5 //Esta constante define o número de níveis (número de caracteres numa permutação)
#define NUMEROS 2 //Esta constante define o número de números pelo qual a permutação passa.
 
int n[NMAX]; //Define o vetor "n" que contém os números pelo qual a permutação vai passando.
 
void permuta(int nivel) { //Inicia função que faz a permutação
        int i; //Define a variável i (contadora)
 
        if (nivel< =NIVELMAX) { //Se o nível for menor ou igual o nível
                for (i=1; i<=NUMEROS; i++) { //Laço para chamar uma função para cada valor diferente desse.
                        n[nivel]=i; //Define o número atual para i (o valor do laço)
                        permuta(nivel+1); //Chama a função (continua a recursão)
                } //Fim-para
        } else { //Senão
                //Imprime todas os números
                for (i=1; i<=NIVELMAX; i++) { //Laço para pegar os números de todas as funções
                        printf("%d", n[i]);
                } //Fim-para
                printf("n"); //Pula uma linha
        } //Fim-se
} //Fim da função
 
int main(void) { //Começa a função "main"
        int i; //Define a variável i (contadora)
 
        //Primeiro, zeramos o vetor "n" que contém os números que vão ser escritos.
        for (i=1; i<=NIVELMAX; i++) { //Laço
                n[i]=1;
        } //Fim-para
 
        //Chama a função com nível 1.
        permuta(1);
} //Fim-função

Esse código tá tão comentado que tá até difícil de entender…

O que você dá para o programa são as três constantes nas linhas 3, 4 e 5.

Gostei de fazer esse programa. Eu tive que pensar um pouco até na hora de escolher trabalhar com vetores, pois fazer permutações parece uma coisa mais simples mas é difícil. Fiz vários rascunhos de algoritmos no papel, mas aí só tá implementado em C. (eu nunca digito meus algoritmos… :blink: )

Comecei a estudar mais expressões regulares (para desenvolver um novo sistema de bbcodes e sintaxe colorida) e estou achando super legal. É um pouco complicado, mas tem muita lógica e tem muitas coisas úteis que dá pra fazer com elas, principalmente na construção de sites interativos em PHP. Estou lendo o livro do Aurélio que está disponível em guia-er.sourceforge.net. É muito bom! :)

Esse cara é um pouco maluco, mas o que ele faz com expressões regulares é muito legal! Desde setembro/2004, eu utilizo um programa em Bash dele chamado Funções ZZ. As funções ZZ são vários aplicativos simples que utilizam expressões regulares para facilitar tarefas do dia-a-dia. Por exemplo, o conceito de permutação que eu utilizei acima foi de um dicionário on-line das funções ZZ.

Consultando as estatísticas hoje, fiquei feliz ao ver meu blog citado em projetando.blogspot.com. Nunca sei se meus textos estão sendo compreendidos e por isso acho legal quando vejo que alguém linkou para meu site.