Cosas web, algunas úles, algunas buenas.
Fushioko, tiendas de productos de Asia

domingo, febrero 12, 2006

Contar palabras usando expresiones regulares

Gracias a que Microsiervos (en particular Nacho) ha puesto un enlace a mi blog en una de sus entradas, lo que cuento sobre las expresiones regulares ha sido de lo más leido en display: NONE. [Actualizado: según me cuenta Mario, él visitó la página gracias a Denker, cuando puse la entrada aún no había visto las estadísticas y la verdad es que también tengo que darle las gracias a Denker y a Error 500 por haberme puesto en sus blogs]. Supongo que debido a ello, Caso Patologico me pregunta en un comentario si sé de algún script que cuente palabras. Pues sin irnos del tema, voy a explicar como lo haría yo usando las expresiones regulares.
En el ejemplo que voy a mostrar, lo que hago es pasar a una función como parámetro un objeto HTML (en este caso un DIV), obtendré el código HTML usando la propiedad innerHTML, después quitaré las etiquetas HTML (<...>) y por último contaré las palabras.
Quizás fuera más sencillo pasar directamente el texto que quiero tratar, pero pasando el objeto también muestro como quitar etiquetas HTML usando las expresiones regulares.
El código sería el siguiente:

    function contarPalabras(obj) {         var txt = obj.innerHTML;                  // Borro todo aquello que esté         // contenido entre < y >         txt = txt.replace(/<(\/|\w|\s|=|"|\n)*>/g, "");                  // Almaceno las coincidencias con palabras         // Al hacer copy/paste debeis ponerlo todo en una línea         var palabras = txt.match(/(\w|á|é|í|ó|ú|ü|ñ|Ñ|Á|É|Í|Ó|Ú)+             [\s\n\r\t,\.;:"'\(\)\{\}\[\]$]*/g);         alert(palabras.length);     }

Así, a simple vista, puede ser fácil no comprender mucho, pero si nos detenemos un poco a intentar entender el contenido de las expresiones regulares, veremos que no es tan difícil.

/<(\/|\w|\s|=|"|\n)*>/g

Esta expresión regular es la que se encarga de reconocer las etiquetas HTML:
  • Primero nos encontramos con un <, que es por lo que empieza cualquier etiqueta HTML
  • Después nos encontramos con un conjunto de caracteres entre paréntesis y separados por |, esto quiere decir que el carácter siguiente está dentro de esos posibles valores:
    • \/ representa a /, es necesario escaparla porque tiene significado propio.
    • \w representa cualquier valor alfanumérico
    • \s representa cualquier el espacio en blanco
    • \n representa el retorno de carro
    • " y = se representan a ellos mismos
  • El conjunto anterior está seguido por *, que indica que puede o no aparecer, y en ese caso, aparecer tantas veces como quiera
  • Y por último encontramos un > que es el carácter final de las etiquetas HTML
  • La g al final indica que se hace una búsqueda global, no finaliza al encontrar el primer caso
Al final lo que tenemos es una expresión regular que detecta todo conjunto de palabras (con números), espacios, comillas, iguales y saltos de línea encerrados entre < y >.
La siguiente expresión regular es la que detecta las palabras y si que nos puede parecer complicada de entender, pero es más sencilla aún que la anterior. Vamos a usar la funcion match la cual nos devuelve una lista con las coincidencias de la expresión regular, y viendo el número de elementos que tiene la lista, sabremos cuantas palabras hay.

/(\w|á|é|í|ó|ú|ü|ñ|Ñ|Á|É|Í|Ó|Ú)+[\s\n\r\t,\.;:"'\(\)\{\}\[\]$]*/g

Esta expresión regular encuentra las palabras seguidas por caracteres que separan palabras (espacios, signos de puntuación, ...):
  • Primeramente hay un grupo de caracteres entre paréntesis, seguido de un + (que indica que se repite una vez o varias). Realmente solo debería aparecer el carácter \w que representa a cualquier carácter alfanumérico, pero no sé por qué (quizás solo en Firefox) no reconoce las vocales acentuadas, ...
  • Después hay un conjunto de caracteres separadores de palabras, incluido el final de cadena ($)
Por lo que reconocerá palabras seguidas de caracteres separadores, separando así las palabras.

9 Comentarios:

  • wow! Se ve muy bien el código, ahora mismo lo voy a probar.

    Por cierto, llegué aqui a través de Denker http://www.uberbin.net/archivos/week-logs/week-log162-2.php

    saludos y muchas gracias por el código!
    Mario

    Por Blogger Mario, a las 2/13/2006 08:56:00 a. m.  

  • La verdad es que no pensé que fuera por Denker porque la página que comentaste fue la de las expresiones regulares, que parecía que era la única que visitaba la gente, según las estadísticas. Pero la verdad sea dicha, gracias a Denker y a Error 500 he conseguido más visitas que con Microsiervos. Que decir... gracias a los 3 y a los que me leen... (parezco a alguien que le han dado un Oscar).

    No, en serio, si ves algún fallo en el script para tu entrada, pues me lo comentas y vemos como podemos ir mejorándolo.

    Saludos
    Luis

    Por Anonymous Anónimo, a las 2/13/2006 09:26:00 a. m.  

  • Si, estás comenzando este blog y pinta muy bien, felicidades, y has sido bendecido por los grandes :D.

    El script me funcionó muy bien!! Mejor que el que tenía, solo le tuve que hacer unos pequeños ajustes:

    1.- El signo < de la tercer línea es un bug ;)
    2.- en el txt.replace sustituí "" por " " (con un blanco), esto es porque a veces juntaba dos palabras.
    3.- En el mismo txt.replace le agregué los caracteres: |\.|:|;|-
    Esto lo tuve que hacer porque blogger agrega automáticamente cierto código (para las imagenes) por default en cada post y no lo "borraba".
    4.- Como observación, el var palabras=txt.match... todo va en una misma línea. Al copiar/pegar el código lo hace en dos líneas y no funcionaba así.

    Saludos y gracias nuevamente.
    Mario

    Por Blogger Mario, a las 2/13/2006 09:59:00 a. m.  

  • Cierto, el "<" es un error a la hora de pasar el script al blogger.
    Y lo del match va en la misma línea, es que si no la cortaba desaparecía debajo del sidebar.

    Ahora corrijo los dos fallos.

    Gracias por tu aportación.

    P.D.: Pues si que estoy teniendo suerte!!

    Por Anonymous Anónimo, a las 2/13/2006 12:24:00 p. m.  

  • Esto de las expresiones regulares es un gustazo. Aun no las domino muy bien y yo para hacer esa "tontería" hubiese escrito muchísimo código inútil. Gracias.

    Por Anonymous Anónimo, a las 2/13/2006 05:28:00 p. m.  

  • Me alegro de que hayas descubierto las expresiones regulares, ya iré poniendo más con el tiempo.

    Saludos.

    Por Anonymous Anónimo, a las 2/13/2006 08:52:00 p. m.  

  • Para no tener problemas con el código que excede el ancho, encierra el código entre las etiquetas <pre style="overflow:auto;"> y </pre>

    saludos!
    Mario

    Por Blogger Mario, a las 2/16/2006 11:05:00 a. m.  

  • Si, lo había pensado, pero no me llega a gustar que aparezcan los scrolls

    Por Anonymous Anónimo, a las 2/16/2006 11:49:00 a. m.  

  • Genial, muy buen trabajo. Me podrias pasar el codigo completo a la direccion davimemonic@hotmail.com ??
    Estoy cn C# en visual Studio y no consigo que encuentre palabras...
    stoy hecho un lio

    Por Anonymous Anónimo, a las 2/25/2009 05:59:00 p. m.  

Publicar un comentario

<< Inicio