<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>El Codiguero</title>
	<atom:link href="http://elcodiguero.com/feed" rel="self" type="application/rss+xml" />
	<link>http://elcodiguero.com</link>
	<description>Programando para la wé</description>
	<pubDate>Wed, 29 Apr 2009 12:11:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>¿Javascript, o «script de Java»?</title>
		<link>http://elcodiguero.com/programacion/241-%c2%bfjavascript-o-%c2%abscript-de-java%c2%bb</link>
		<comments>http://elcodiguero.com/programacion/241-%c2%bfjavascript-o-%c2%abscript-de-java%c2%bb#comments</comments>
		<pubDate>Mon, 26 Jan 2009 01:31:08 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Opiniones y comentarios]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://elcodiguero.com/?p=241</guid>
		<description><![CDATA[He escuchado demasiadas veces la frase script de Java referida a Javascript. Probablemente se trate de una mala traducción que desafortunadamente fue considerada correcta, pero la verdad es que escucharla de un ingeniero en sistemas me choca, y mucho. Saber que gente que sabe piensa que Javascript es simplemente un subconjunto de Java es muy [...]]]></description>
			<content:encoded><![CDATA[<p>He escuchado demasiadas veces la frase <q>script de Java</q> referida a <a href="http://es.wikipedia.org/wiki/Javascript">Javascript</a>. Probablemente se trate de una mala traducción que desafortunadamente fue considerada correcta, pero la verdad es que escucharla de un ingeniero en sistemas me choca, y mucho. Saber que gente <q>que sabe</q> piensa que Javascript es simplemente un subconjunto de <a href="http://www.java.com">Java</a> es muy frustrante. Por eso es mi intención ahora mismo nombrar alguna de las diferencias que se me vienen a la mente, simplemente para tenerlo como referencia la próxima vez que me toque explicarle a alguien por qué Javascript NO significa <q>script de Java</q>.</p>
<p>Exponer las diferencias entre Java y Javascript se ha hecho muchas veces antes, pero tengo la sensación de que la mayoría de las veces que se escribió sobre el tema se hizo siendo Javascript un lenguaje despreciado y considerado casi un <q>juguetito</q> de las páginas web. Javascript es mucho más que <q>un Java básico y con algunas cosas raras</q>, e intentaré hacer valer eso en este artículo.</p>
<h2>Historia</h2>
<p>Dejaré que Wikipedia mencione los detalles sobre la <a href="http://es.wikipedia.org/wiki/Javascript#Historia_y_denominaci.C3.B3n">historia del lenguaje</a>. Lo principal en esta historia es que el lenguaje que hoy conocemos como Javascript comenzó su vida llamándose LiveScript: el cambio de nombre fue únicamente (según algunos) para aprovechar la publicidad que se hacía en la época a Java y el impulso comercial que éste estaba teniendo.</p>
<h2>Ejecución</h2>
<p>Partiendo en ambos lenguajes de un código fuente válido, el proceso que sigue un programa en Java es bastante diferente al que sigue un programa en Javascript.</p>
<h3>Java</h3>
<p>Un programa Java se compila, generando un archivo .class por cada clase o un <acronym xml:lang="en" title="JAva Archive"><a href="http://es.wikipedia.org/wiki/Jar">JAR</a></acronym> que incluye todas las clases.<br />
Es la <acronym xml:lang="en" title="Java Virtual Machine"><a href="http://es.wikipedia.org/wiki/JVM">JVM</a></acronym> (Máquina Virtual de Java) la que luego ejecuta el programa.</p>
<h3>Javascript (en un navegador)</h3>
<p>El código fuente Javascript se incluye en la página <acronym title="HyperText Markup Language" xml:lang="en"><a href="http://es.wikipedia.org/wiki/HTML">HTML</a></acronym> mediante una etiqueta <code class="linea">&lt;script></code> o <code class="linea">&lt;link></code> en el caso de un archivo externo. El navegador interpreta el código y lo ejecuta en un entorno restringido a la página desde la cual es vinculado.</p>
<h2>Sintaxis</h2>
<p>Tanto Java como Javascript utilizan una sintaxis basada en C.<br />
Se podría decir que Java se parece más a C++, mientras que Javascript se parece más a C.</p>
<h2>Tipos de datos</h2>
<p>Java incluye los <a href="http://es.wikipedia.org/wiki/Tipo_de_dato">tipos de datos</a> básicos <q>integer</q> (y derivados), <q>String</q>, <q>boolean</q>, <q>float</q> y <q>double</q>. Además, cada clase es un tipo de dato con el que podemos crear variables. Una variable de un tipo no puede redefinirse como de otro (a menos que <q>otro</q> sea superclase de <q>uno</q>), y se aplican comprobaciones estrictas de tipos. A esto se le llama <q><a href="http://es.wikipedia.org/wiki/Lenguaje_de_programación_fuertemente_tipado">tipado fuerte</a></q>.</p>
<p>Javascript solamente posee los tipos de datos <q>number</q>, <q>object</q>, <q>string</q>, <q>function</q>. Las variables se definen sin tipo, serán del tipo que sea aquello que se les está asignando. A una variable definida de cierto tipo se le puede asignar un valor de otro tipo (por ejemplo, a una variable entera puede asignársele una cadena), y el tipo de dato de la variable cambia. A esto se le llama <q><a href="http://es.wikipedia.org/wiki/Tipado_dinámico">tipado dinámico</a></q>.<br />
Veamos un par de ejemplos para ver la diferencia. Primero, código Java:<br />
<code class="prettyprint">String variable = "Hola"; <-- variable se declara de tipo String
variable = 1; <-- dará un error de compilación, no se puede asignar un entero.</code><br />
Y ahora un código equivalente en Javascript:<br />
<code class="prettyprint">var variable = "Hola"; <-- variable se declara sin tipo. Como se le asigna una cadena, tendrá el tipo String
variable = 1; <-- variable es ahora de tipo entero. No hay errores de ningún tipo :-D</code></p>
<h2>Ámbito de las variables</h2>
<p>Java, al igual que la mayoría de los lenguajes basados en C, tiene variables de bloque. Es decir, que una variable definida en un bloque de código (delimitado por las llaves { y }) existirá solamente dentro de ese bloque. En caso de producirse ambigüedad (una variable <q>local</q> al bloque se llama igual que una variable externa) tiene prioridad el espacio de nombres local.</p>
<p>En Javascript, por otra parte, solamente las funciones generan su propio espacio de nombres. Los bloques de código utilizan las variables definidas fuera, y si definen alguna variable ésta no desaparecerá cuando el programa salga del bloque, sino que seguirá definida en el espacio de nombres global (o de la función en la que esté el bloque).<br />
Esto es algo bastante molesto en realidad, ya que puede fácilmente generar conflictos y es una de las principales razones (por si no hubiera ya suficientes) para evitar las variables globales.</p>
<h2>Funcional</h2>
<p>En java las funciones NO son un tipo de datos. En Javascript sí: una función es una variable como cualquier otra, que se puede pasar como parámetro a otra función o asignar a una variable. Incluso se pueden declarar funciones anónimas para utilizarlas una sola vez y que no ocupen el espacio de nombres. Se dice que una función es un <a href="http://en.wikipedia.org/wiki/First-class_data_type"><q>tipo de dato de primera clase</q></a>. Esto, junto con otras características, hacen que javascript sea un lenguaje funcional, y, en palabras del experto <a href="http://www.crockford.com">Douglas Crockford</a>, <q xml:lang="en">el primer lenguaje lambda en llegar a utilizarse masivamente</q>. (donde <em>lambda</em> proviene del <a href="http://es.wikipedia.org/wiki/Cálculo_lambda">cálculo lambda</a>, y es otro nombre para una función anónima.)</p>
<h2>Orientación a Objetos</h2>
<p>Java es orientado a objetos, como todos sabemos, y utiliza una orientación a objetos <em>clásica</em>, es decir, basada en clases. Los objetos son <em>ejemplares</em> de una clase (disculpen pero detesto utilizar <em>instancia</em> como traducción de <em>instance</em>), y la herencia se da entre clases.</p>
<p>Javascript es también orientado a objetos, pero no usa clases, aunque hay formas de simularlas y se utiliza algo similar a una clase al crear un objeto de tipo <strong>Date</strong>.<br />
En Javascript la herencia se da directamente entre objetos, mediante <a href="http://es.wikipedia.org/wiki/Programación_basada_en_prototipos">prototipos</a>. Todo objeto contiene un atributo oculto que lo vincula a su objeto padre, formando una cadena hasta el objeto padre <strong>Object</strong> (que en los navegadores es <samp class="linea">window</samp>).</p>
<p>Un objeto hereda todos los métodos y atributos de su objeto padre, y si al objeto padre se le agrega un método o atributo, los objetos hijos podrán ver inmediatamente el nuevo miembro añadido. Todo objeto contiene un atributo <q>prototype</q> al que se puede agregar miembros (atributos o métodos) para que todos los objetos hijos puedan verlos. Por ejemplo, si agrega un método metodo a <em>String.prototype</em>, todas las cadenas contendrán el método.</p>
<h2>Conclusión</h2>
<p>Espero que este repaso por algunas de las principales diferencias entre Java y Javascript sirva de algo, con un poco de suerte estaré ayudando a que ya nadie piense en Javascript como un hermanito menor de Java. Para aquellos que quieran profundizar en el lenguaje, recomiendo los videos disponibles en el <a href="http://developer.yahoo.com/yui/theater/" xml:lang="en">YUI Theater</a> y el libro <a xml:lang="en" href="http://www.amazon.com/exec/obidos/ASIN/0596517742/">Javascript: The Good Parts</a> de Douglas Crockford.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/241-%c2%bfjavascript-o-%c2%abscript-de-java%c2%bb/feed</wfw:commentRss>
		</item>
		<item>
		<title>Des-formateador v0.2</title>
		<link>http://elcodiguero.com/wordpress/230-desformateador</link>
		<comments>http://elcodiguero.com/wordpress/230-desformateador#comments</comments>
		<pubDate>Sun, 28 Dec 2008 14:56:02 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://elcodiguero.com/?p=230</guid>
		<description><![CDATA[Descripción
Des-formateador es un plugin para WordPress que provoca que cualquier etiqueta sea tratada por éste de la misma forma que &#60;pre>. Es decir, el formato en el que se escribe es preservado.
El problema
Quienes programamos y publicamos código en nuestros respectivos blogs, nos hemos encontrado con la mala costumbre que WordPress tiene, formatear los saltos de [...]]]></description>
			<content:encoded><![CDATA[<h2>Descripción</h2>
<p><strong>Des-formateador</strong> es un <span xml:lang="en">plugin</span> para <a href="http://www.wordpress.org">WordPress</a> que provoca que cualquier etiqueta sea tratada por éste de la misma forma que <code class="linea">&lt;pre></code>. Es decir, el formato en el que se escribe es preservado.</p>
<h2>El problema</h2>
<p>Quienes programamos y publicamos código en nuestros respectivos blogs, nos hemos encontrado con la <q>mala costumbre</q> que WordPress tiene, formatear los saltos de línea de todas las etiquetas a excepción de <code class="linea">&lt;pre></code>.<br />
Lo cual no sería un problema sino fuera porque para el código de programación disponemos de la etiqueta <code class="linea">&lt;code></code>, y para la publicación de códigos de ejemplo (o la salida de un programa) disponemos de <code class="linea">&lt;samp></code>.</p>
<p>La forma habitual de publicar código con estas etiquetas es utilizar la propiedad <code class="linea">word-wrap</code> de <acronym title="Cascade Style Sheets - Hojas de Estilo en Cascada">CSS</acronym>, para así lograr un aspecto visual igual al que se logra con la etiqueta <code class="linea">&lt;pre></code>. Sin embargo, si se combina esta propiedad con el comportamiento por defecto de WordPress, el resultado es que todos los saltos de línea se duplican.</p>
<h2>La solución</h2>
<p>Lo que hace este <span xml:lang="en">plugin</span> es ejecutar sobre las etiquetas definidas la misma función que ejecuta WordPress para la etiqueta <code class="linea">&lt;pre></code>, removiéndoles el formato.<br />
La única configuración necesaria (y posible) es la definición de las etiquetas cuyo formato será preservado. De forma predefinida estas etiquetas son <code class="linea">&lt;code></code> y <code class="linea">&lt;samp></code>. Esta configuración se realiza editando el <span xml:lang="en">plugin</span> y añadiendo las etiquetas deseadas a la matriz <var>$etiquetas</var></p>
<h2>Descarga</h2>
<p>Por ahora no he trabajado lo suficiente en el programa como para subirlo al repositorio oficial de <span xml:lang="en">plugins</span> de WordPress, pero se puede descargar desde aquí:</p>
<p><a href="/archivos/desformateador.php.zip">Des-formateador v0.2</a></p>
<h2>Cambios</h2>
<ul>
<li>Versión 0.2: corregido un problema en la expresión regular utilizada.</li>
<li>Versión 0.1: versión original</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/wordpress/230-desformateador/feed</wfw:commentRss>
		</item>
		<item>
		<title>Slackware 12.2: Instalación</title>
		<link>http://elcodiguero.com/linux/210-slackware-122-instalacion</link>
		<comments>http://elcodiguero.com/linux/210-slackware-122-instalacion#comments</comments>
		<pubDate>Fri, 26 Dec 2008 02:43:18 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://elcodiguero.com/?p=210</guid>
		<description><![CDATA[
Hace un par de semanas fue publicada la versión 12.2 de Slackware, la distribución de GNU/Linux más antigua entre las que siguen desarrollándose.
Esta distribución se caracteriza por su fama de complicada, sin embargo una vez que el sistema está configurado el mantenimiento necesario es mínimo, y resulta tan sencilla de manejar como cualquier otra distribución. [...]]]></description>
			<content:encoded><![CDATA[<div class="t_centrado"><a href="http://www.slackware.com" title="Ir al sitio de Slackware"><img src="/archivos/slackware.png" title="Logo de Slackware" /></a></div>
<p>Hace un par de semanas fue publicada la versión 12.2 de <a href="http://www.slackware.com">Slackware</a>, la distribución de <a href="http://es.wikipedia.org/wiki/GNU/Linux">GNU/Linux</a> más antigua entre las que siguen desarrollándose.<br />
Esta distribución se caracteriza por su fama de <q>complicada</q>, sin embargo una vez que el sistema está configurado el mantenimiento necesario es mínimo, y resulta tan sencilla de manejar como cualquier otra distribución. Lo único que el sistema pide <q>a cambio</q> de su estabilidad y facilidad de mantenimiento es algo de tiempo leyendo manuales y ayudas para comprender lo que sucede y por qué. La instalación, configuración y uso de este sistema es probablemente la mejor forma de aprender a manejar un sistema Unix.</p>
<p>Queda claro que le tengo un aprecio bastante grande, sin embargo soy capaz de reconocer que, como todo, esta distribución no es perfecta y tiene sus problemas. Y para solucionar los problemas suele requerirse un conocimiento de lo que se hace. Es por eso que quiero compartir mi experiencia instalando Slackware 12.2 en mi computadora <a href="http://en.wikipedia.org/wiki/Dell_Vostro">Dell Vostro 1000</a>.</p>
<h2>Instalación</h2>
<p>La instalación en sí no es un problema, recomiendo <a href="http://manual.zenwalk.org/manual_es.pdf">esta guía de instalación</a> para aquellos que no hayan realizado este proceso antes. La guía es para la distribución <a href="http://www.zenwalk.org">ZenWalk</a>, pero el proceso es casi el mismo ya que <em>ZenWalk</em> es una de las tantas distribuciones <q>hijas</q> de Slackware.</p>
<p>Un punto a recordar es que, una vez en el programa de instalación, debe iniciarse el proceso eligiendo la opción <strong>ADDSWAP</strong> en el menú, o <strong>TARGET</strong>. Estos pasos deben hacerse primero ya que son los que preparan el disco en el que se instalará, si no se hacen primero <em>siempre se llega a un punto en la instalación en el que se debe iniciar todo el proceso de nuevo</em>.<br />
Y esto siempre requiere salir del programa de instalación y abrirlo de nuevo, ya que la autodetección del disco CD/DVD de instalación <em>funciona solamente la primera vez que se hace</em>.</p>
<p>De todas formas, la instalación con las opciones por defecto (<em xml:lang="en">full install</em>, instalar todos los paquetes disponibles) puede iniciarse en menos de 5 minutos y terminarse en más o menos media hora.</p>
<p>Al terminar la copia de archivos se hacen algunos pasos para la configuración inicial del sistema, principalmente lo que respecta a la ubicación geográfica, la configuración de red y la instalación del gestor de arranque (<a href="http://es.wikipedia.org/wiki/Lilo_(Linux)">LILO</a>). Una vez finalizados estos pasos, el programa de instalación se cierra y se nos indica que debemos reiniciar el sistema.</p>
<h2>Configuración inicial</h2>
<p>Al arrancar el sistema, a diferencia de lo que sucede con otras distribuciones, el entorno gráfico no se inicia por defecto. Se nos presenta una pantalla de inicio de sesión en modo texto, en la que deberemos entrar como el usuario <q>root</q> y con la contraseña correspondiente (que habremos indicado en uno de los últimos pasos de la instalación).</p>
<p>Una vez dentro, hay varias tareas a realizar.</p>
<h3>Arrancar por defecto el entorno gráfico</h3>
<p>Esto se hace editando el archivo <samp class="linea">/etc/inittab</samp> y cambiando el <a href="http://es.wikipedia.org/wiki/Nivel_de_ejecución">nivel de ejecución</a> predeterminado. Lo haremos con <samp class="linea"><a href="http://es.wikipedia.org/wiki/Vim">vim</a></samp><br />
<samp>root@alvlin:/# vim /etc/inittab</samp><br />
Una vez que se abra el archivo, hay que ir a la línea que contiene<br />
<samp># Default runlevel. (Do not set to 0 or 6)
id:3:initdefault:</samp></p>
<p><samp class="linea">vim</samp> no se parece en nada a los editores <q>normales</q>, por lo que para quien lo usa por primera vez puede resultar bastante extraño. La forma más sencilla de editar lo necesario y salir es llevar el cursor hacia el <strong>3</strong> en la línea mencionada antes, y presionar la siguiente secuencia de teclas:</p>
<ul>
<li><strong>x</strong> : borrará el 3</li>
<li><strong>i</strong> : cambiará a <q>modo edición</q></li>
<li><strong>4</strong> : escribirá un 4</li>
<li><strong>:wq</strong> : este comando guarda el archivo y sale de <samp class="linea">vim</samp>
</ul>
<p>Con esto, se indica que el nivel de ejecución por defecto debe ser el nivel 4. Normalmente cualquier documentación de GNU/Linux que se encuentre indica que el nivel 4 no se utiliza, y además casi todas las demás distribuciones utilizan el nivel 5 para el modo gráfico. En esto Slackware es diferente, en tanto que utiliza el nivel 4 para el modo gráfico y no utiliza el nivel 5.</p>
<p>Lo único que resta es configurar correctamente el <a href="http://es.wikipedia.org/wiki/X_Window_System">servidor X</a>, para esto basta ejecutar el programa <samp class="linea">xorgsetup</samp>, que se encargará de escribir un archivo de configuración inicial correcto.</p>
<h3>Crear un usuario sin privilegios</h3>
<p>La forma usual de utilizar el sistema es como usuario sin privilegios. Esto es, sin permiso para instalar programas o modificar el sistema, únicamente se tiene permiso para hacer modificaciones en la carpeta asignada al usuario. Este modo es ideal por la seguridad y para evitar errores fatales, que casi todos hemos cometido alguna vez. Añadiremos un usuario, entonces, con el comando <samp class="linea">adduser</samp> y escribiendo la información que el comando solicita.</p>
<p>Para que este usuario sea <q>usable</q>, conviene iniciar el programa <samp class="linea">kuser</samp> y asegurarse de que pertenezca a los grupos <q>audio</q> (para que pueda utilizar la tarjeta de sonido), <q>cdrom</q>, <q>disk</q>, <q>plugdev</q> (para que pueda utilizar dispositivos extraíbles), y <q>video</q>.</p>
<h3>Utilizar el <q xml:lang="en">kernel</q> <q xml:lang="en">generic</q> en lugar de <q xml:lang="en">huge</q></h3>
<p>Para la instalación, y por defecto en la instalación completa, Slackware instala un núcleo Linux que tiene compilado casi todos los controladores disponibles. Esto implica que el núcleo por defecto es bastante grande e ineficiente, aunque en una instalación funciona bien. Para el uso diario es mejor cambiar a un núcleo que incluya solamente lo mínimo, y en el que los controladores estén incluidos en forma de módulos (de tal forma que solamente se cargarán aquellos que sean necesarios).<br />
Este cambio requiere de varias modificaciones, que quizás sea mejor hacer desde el entorno gráfico (se requiere edición de archivos, y es más fácil usar <samp class="linea">kedit</samp> que <samp class="linea">vim</samp>.) Por lo que reiniciar en este momento e iniciar sesión como <em>root</em> en el entorno gráfico puede ser la mejor idea.</p>
<h4>Vincular al <q xml:lang="en">kernel</q> correcto</h4>
<p>Desde la consola, el siguiente comando<br />
<samp>cd /boot ; ls -l</samp><br />
Debería mostrar algo como esto (eliminé algunas líneas innecesarias):<br />
<samp>lrwxrwxrwx  1 root root      37 2008-12-20 00:44 README.initrd -> /usr/doc/mkinitrd-1.3.3/README.initrd
lrwxrwxrwx  1 root root      35 2008-12-18 00:49 System.map -> System.map-huge-smp-2.6.27.7-smp
-rw-r--r--  1 root root  965704 2008-11-21 02:20 System.map-generic-smp-2.6.27.7-smp
lrwxrwxrwx  1 root root      32 2008-12-18 00:49 vmlinuz -> vmlinuz-huge-smp-2.6.27.7-smp
-rw-r--r--  1 root root 2347888 2008-11-21 02:20 vmlinuz-generic-smp-2.6.27.7-smp</samp><br />
Los archivos <samp class="linea">System.map</samp> y <samp class="linea">vmlinuz</samp> son enlaces que apuntan a las versiones <q xml:lang="en">huge</q> del núcleo (esto puede verse indicado por las flechas -> junto al nombre del archivo). Debemos vincularlas a las versiones <q xml:lang="en">generic</q>. Para esto, se utilizan los siguientes comandos:<br />
<samp>rm System.map vmlinuz
ln -s vmlinuz-generic-smp-2.6.27.7-smp vmlinuz
ln -s System.map-generic-smp-2.6.27.7-smp System.map</samp><br />
Obviamente conviene hacer uso del autocompletado en <a href="http://es.wikipedia.org/wiki/Bash">bash</a>, para no tener que recordar todo el nombre del archivo (presionar tecla tabulador).</p>
<p>El siguiente paso es crear el <a href="http://es.wikipedia.org/wiki/Initrd">archivo initrd</a> requerido. Dado que el núcleo genérico no tiene los controladores en el núcleo mismo sino como módulos, es necesario brindarle algunos controladores iniciales para que pueda encontrar el disco duro, leerlo, y cargar el resto de los módulos que necesita. Estos controladores iniciales se guardan en el archivo initrd.<br />
Las instrucciones necesarias para crear este archivo están en el archivo <samp class="linea">README.initrd</samp> dentro de la carpeta <samp class="linea">/boot</samp>. Básicamente, para un sistema cuya partición principal es de tipo <samp class="linea"><a href="http://es.wikipedia.org/wiki/Ext3">ext3</a></samp>, y está en <samp class="linea">/dev/sda1</samp> (la primera partición primaria del primer disco <a href="http://es.wikipedia.org/wiki/Sata">SATA</a>), el comando necesario es<br />
<samp>mkinitrd -c -k 2.6.27.7-smp -m mbcache:jbd:ext3 -f ext3 -r /dev/sda1</samp><br />
(dentro de la carpeta <samp class="linea">/boot</samp>)<br />
El último paso ahora es configurar <span xml:lang="en">LILO</span> para que cargue este archivo <span xml:lang="en">initrd</span>. Habrá que editar el archivo <samp class="linea">/etc/lilo.conf</samp>, buscar la sección correspondiente y agregar una línea al bloque<br />
<samp># Linux bootable partition config begins
image = /boot/vmlinuz
root = /dev/sda1
label = Linux
read-only
# Linux bootable partition config ends</samp></p>
<p>que deberá quedar como<br />
<samp># Linux bootable partition config begins
initrd = /boot/initrd.gz
image = /boot/vmlinuz
root = /dev/sda1
label = Linux
read-only
# Linux bootable partition config ends</samp></p>
<p>Ya que estamos editando el archivo <samp class="linea">lilo.conf</samp>, conviene también editar el tiempo que se espera antes de arrancar el sistema, en la pantalla de selección de <acronym title="Sistema Operativo"><a href="http://es.wikipedia.org/wiki/SO">SO</a></acronym>. Por defecto este tiempo es 2 minutos, recomiendo cambiarlo a un tiempo que sea corto pero permita interrumpir el proceso en caso de ser necesario (por ejemplo, medio segundo)<br />
Habrá que ir hacia el principio del archivo lilo.conf y cambiar:<br />
<samp># This is given in tenths of a second, so 600 for every minute:
timeout = 1200</samp><br />
por<br />
<samp># This is given in tenths of a second, so 600 for every minute:
timeout = 50</samp></p>
<p>Una vez realizados estos cambios, hay que re-instalar <span xml:lang="en">LILO</span>. Este proceso es simplemente ejecutar el comando <samp class="linea">lilo</samp> en la terminal. Recomiendo ejecutar primero <samp class="linea">lilo -t</samp> (hacer una simulación de la instalación) y luego, si no hay errores (puede haber advertencias), ejecutar <samp class="linea">lilo</samp>.</p>
<p>Ahora, reiniciar el sistema nuevamente para cargar el núcleo genérico.</p>
<h2>Configuración de una computadora portátil</h2>
<p>Si tienes una computadora de escritorio, no se requieren más detalles de configuración, todo debería haber sido reconocido y autoconfigurado. El resto será cuestión de configurar los detalles del entorno gráfico. Pero si como yo tienes una computadora portátil, habrá otros detalles a configurar.</p>
<h3>Red inalámbrica</h3>
<p>Es muy probable que el dispositivo de red inalámbrica no tenga controladores para Linux. En este caso habrá que apelar a <a href="http://es.wikipedia.org/wiki/NDISwrapper">ndiswrapper</a>, un programa que es capaz de utilizar los controladores de Windows que estos dispositivos incluyen. ndiswrapper no está incluido en la distribución de Slackware, pero puede conseguirse sin dificultad en <a href="http://www.slackbuilds.org">SlackBuilds.org</a>.<br />
Para el control de la red inalámbrica Slackware incluye el programa <a href="http://wicd.sourceforge.net">wicd</a> en la carpeta <samp class="linea">/extra</samp>. Bastará entonces con instalar el paquete desde esa carpeta. Algo importante a recordar es que, para que <samp class="linea">wicd</samp> funcione correctamente, es necesario darle permisos de ejecución al archivo <samp class="linea">/etc/rc.d/rc.wicd</samp>, y más importante aún: <strong>remover la configuración que se encuentra en el archivo <samp class="linea">/etc/rc.d/rc.inet1.conf</samp></strong>. Para lograr esto simplemente se agrega una almohadilla <q>#</q> a toda línea de este archivo que no comience con una.<br />
Si todo va bien entonces, al reiniciar habrá un ícono de <samp class="linea">wicd</samp> al lado del reloj, pronto para conectarse a alguna de las redes detectadas.</p>
<h3>Synaptics, el controlador para el <q xml:lang="en">touchpad</q></h3>
<p>El controlador synaptics viene incluido en Slackware, pero no será activado por defecto. Para activarlo, se requiere editar el archivo <samp class="linea">/etc/X11/xorg.conf</samp>. Este archivo contiene una sección por cada dispositivo de entrada (ratón, teclado), para el monitor, para la tarjeta de video, etc. Deberemos editar la sección correspondiente al ratón.<br />
Esta sección es fácil de encontrar, habrá una línea como la siguiente:<br />
<samp>Identifier &#034;Mouse0&#034;</samp><br />
Habrá que cambiar algunas líneas, para que quede similar a lo siguiente:<br />
<samp>Section &#034;InputDevice&#034;
        Identifier  &#034;TouchPad&#034;
        Driver      &#034;synaptics&#034;
        Option      &#034;Protocol&#034; &#034;auto-dev&#034;
        Option      &#034;Device&#034; &#034;/dev/input/by-path/platform-i8042-serio-1-event-mouse&#034;
        Option      &#034;SHMConfig&#034; &#034;On&#034;
EndSection</samp><br />
Las líneas importantes son <samp class="linea">Protocol</samp> y <samp class="linea">Driver</samp>. La opción <samp class="linea">SHMConfig</samp> permite cambiar parámetros del <span xml:lang="en">touchpad</span> al vuelo (por ejemplo, permite desactivarlo de forma temporal), mientras que para cambiar la línea <samp class="linea">Device</samp> se requiere un buen motivo.<br />
Yo lo cambié porque noté que si iniciaba la computadora con mi ratón USB conectado, el nombre de dispositivo que le tocaba al <span xml:lang="en">touchpad</span> era diferente. Por lo que resultaba que a veces funcionaba y a veces no. Para solucionar esto, le escribí como nombre de dispositivo algo que sabía que siempre se asigna igual (o mejor dicho, un nombre que se asigna al lugar correcto siempre). Normalmente el parámetro <samp class="linea">Device</samp> funciona sin problemas con un valor similar a <samp class="linea">/dev/input/eventN</samp> (donde N es un número)</p>
<p>Otro cambio necesario para el <span xml:lang="en">touchpad</span> es cambiar la forma en que trabaja el módulo <span xml:lang="en">psmouse</span> trabaja. Este módulo es un módulo genérico de Linux para ratón, y por defecto viene configurado de tal forma que el <span xml:lang="en">touchpad</span> no se reconoce correctamente.<br />
La configuración que hay que cambiar está en <samp class="linea">/etc/modprobe.d/psmouse</samp>. Habrá que cambiar la línea<br />
<samp>options psmouse proto=ipms</samp><br />
por<br />
<samp>options psmouse proto=any</samp></p>
<p>De esta forma, en el arranque del sistema el touchpad pasará de ser reconocido como<br />
<samp>PS/2 Synaptics TouchPad</samp><br />
a ser reconocido como debe ser:<br />
<samp>SynPS/2 Synaptics TouchPad</samp></p>
<h3>Configuración de ahorro de energía</h3>
<p>KLaptop puede configurar sin grandes problemas parte del sistema de ahorro de energía, pero hay un detalle que debe configurarse editando un archivo: qué se hace cuando se presiona el botón de encendido/apagado.<br />
<a href="http://www.linux.com/articles/54610">En esta página se explica cómo se debe configurar esto</a>, el artículo es viejo y la mayor parte de lo que se explica ya no es necesario (como escribí antes, de eso se encarga KLaptop ahora)<br />
Los pasos para que al presionar el botón la computadora <a href="http://en.wikipedia.org/wiki/Hibernate_(OS_feature)">hiberne</a> en vez de apagarse son los siguientes:</p>
<ol>
<li>Cambiar a la carpeta <samp class="linea">/etc/acpi</samp></li>
<li>Dejar en esta carpeta únicamente el archivo <samp class="linea">acpi_handler.sh</samp> y crear las carpetas <samp class="linea">events</samp> and <samp class="linea">actions</samp> en caso de ser necesario.
<li>
<li>Crear un archivo <samp class="linea">/etc/acpi/actions/pwrbtn.sh</samp> con permisos de ejecución, y con el siguiente contenido:<br />
<samp>#!/bin/sh
klaptop_acpi_helper --hibernate</samp>
</li>
<li>Crear un archivo <samp class="linea">/etc/acpi/events/pwrbtn</samp> con el siguiente contenido:<br />
<samp>event=button[ /]power
action=/etc/acpi/actions/pwrbtn.sh</samp>
</li>
</ol>
<p>Listo, al presionar el botón de encendido la computadora hibernará en vez de apagarse. ¿Pero cómo restaurar?<br />
Lo que hace la hibernación es mover el contenido de la memoria <a href="http://es.wikipedia.org/wiki/Memoria_de_acceso_aleatorio">RAM</a> y de algunas otras cosillas a la partición <a href="http://es.wikipedia.org/wiki/Espacio_de_intercambio">swap</a>. Para poder restaurar el sistema es necesario indicarle al núcleo la partición de <span xml:lang="en">swap</span>.<br />
Hay que editar el archivo <samp class="linea">lilo.conf</samp> de nuevo, buscar la sección de Linux y añadirle la siguiente línea:<br />
<samp>append = &#034;resume=/dev/sda2&#034; </samp><br />
(donde <samp class="linea">/dev/sda2</samp> es la partición de <span xml:lang="en">swap</span>).<br />
Para finalizar, hay que volver a ejecutar el comando <samp class="linea">lilo</samp> (como antes, primero <samp class="linea">lilo -t</samp> para asegurarse de que todo es correcto, luego <samp class="linea">lilo</samp> para hacer la instalación). Con esto, si la máquina fue hibernada, el núcleo restaurará el estado. En caso de que la máquina haya sido apagada, se hará un arranque normal. En mi caso tengo configuradas dos secciones idénticas, una con el <q xml:lang="en">resume</q> y otra sin él, simplemente para hacer pruebas de vez en cuando.</p>
<h2>Toques finales</h2>
<p>Para finalizar, personalmente me gusta instalar dos añadidos que modifican la apariencia de KDE. Uno de ellos es <a href="http://www.kde-look.org/content/show.php?content=25705">kde-moodin-engine</a> (permite crear temas para la pantalla de inicio de KDE) y el otro es <a href="http://www.kde-apps.org/content/show.php/KDM+Theme+Manager?content=22120">kdmtheme</a> (permite crear temas para KDM). Con ellos se logra un arranque bastante bonito, personalmente uso el tema <q xml:lang="en">LoveKDE</q> para kdm y el tema <q xml:lang="en">MoodinKDE</q> para la pantalla de arranque.</p>
<p>Luego de todo esto quizás pienses: ¿por qué complicarse tanto si la distribución X lo hace todo automático? La respuesta, al menos en mi caso, es: <strong>para aprender lo que sucede tras bastidores en el sistema</strong>.</p>
<div class="t_centrado"><a href="http://img376.imageshack.us/my.php?image=moodinkdeyz6.png"><img src="http://img376.imageshack.us/img376/9459/moodinkdeyz6.th.png" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/linux/210-slackware-122-instalacion/feed</wfw:commentRss>
		</item>
		<item>
		<title>Expresiones regulares con PHP - Perl</title>
		<link>http://elcodiguero.com/php/177-expresiones-regulares-con-php-perl</link>
		<comments>http://elcodiguero.com/php/177-expresiones-regulares-con-php-perl#comments</comments>
		<pubDate>Wed, 24 Dec 2008 01:30:07 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=177</guid>
		<description><![CDATA[Nota: Como texto a analizar se utilizará esta página, que es un trozo conveniente de esta otra. Se eligió este texto por ser repetitivo y sencillo de comprender. Para analizarlo, se utilizará el siguiente patrón:
([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &#60;a href=&#034;([^"]+)&#034;&#62;(.*?)&#60;/a&#62;&#60;br&#62;
Introducción
PHP incluye soporte para expresiones regulares en el núcleo mismo del lenguaje, no se requieren extensiones [...]]]></description>
			<content:encoded><![CDATA[<p class="nota">Nota: Como <q>texto a analizar</q> se utilizará <a href="/archivos/ejemplo.txt">esta página</a>, que es un trozo <q>conveniente</q> de <a href="http://antwrp.gsfc.nasa.gov/apod/archivepix.html">esta otra</a>. Se eligió este texto por ser repetitivo y sencillo de comprender. Para analizarlo, se utilizará el siguiente patrón:<br />
<code>([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;([^"]+)&#034;&gt;(.*?)&lt;/a&gt;&lt;br&gt;</code></p>
<h2>Introducción</h2>
<p><a href="http://www.php.net">PHP</a> incluye soporte para expresiones regulares en el núcleo mismo del lenguaje, no se requieren extensiones para habilitarlo. Se soporta por defecto tanto la sintaxis <a href="http://es.wikipedia.org/wiki/POSIX" title="Portable Operating System Interface">POSIX</a> (funciones <em>ereg*</em>) como la sintaxis PERL (funciones <em>preg*</em>).<br /> <br />
Tradicionalmente se prefiere el uso de la sintaxis de Perl, en el entendido de que las funciones correspondientes tienen un mejor rendimiento que sus homólogas POSIX; sin embargo esto varía caso a caso según el tipo de patrón que se utilice. Si el rendimiento es crítico, se deben probar ambos tipos de patrones y comparar sus resultados.</p>
<p>Como mencionaba en una parte anterior de esta serie (<a href="http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias" title="Tipos de coincidencias y referencias">Tipos de coincidencias y referencias</a>), las funciones de expresiones regulares se separan en tres grupos: coincidencia de texto, reemplazo de texto, y separación de cadenas; siendo esta última la opción menos usada.</p>
<h2>Funciones <acronym title="Perl Compatible Regular Expressions" xml:lang="en">PCRE</acronym></h2>
<p>Las funciones que PHP provee para utilizar expresiones regulares con sintaxis Perl son:</p>
<ul>
<li><a href="http://php.net/preg_match">preg_match</a></li>
<li><a href="http://php.net/preg_match_all">preg_match_all</a></li>
<li><a href="http://php.net/preg_replace">preg_replace</a></li>
<li><a href="http://php.net/preg_split">preg_split</a></li>
</ul>
<p>El listado completo de funciones se puede ver en <a href="http://www.php.net/manual/es/ref.pcre.php">http://www.php.net/manual/es/ref.pcre.php</a>.</p>
<p>Los modificadores que provee la biblioteca PCRE (que PHP usa para soportar la sintaxis Perl) se describen en la página del manual de <a href="http://www.php.net/manual/es/reference.pcre.pattern.modifiers.php">Modificadores de Patrón</a>. Dada la existencia del modificador <q>i</q>, no existen funciones diferentes para realizar una comparación sensible a mayúsculas y minúsculas, como en el caso de las funciones <a href="http://elcodiguero.com/php/155-expresiones-regulares-con-php-posix" title="Expresiones regulares con PHP - POSIX">POSIX</a>.</p>
<h3>Coincidencia de texto</h3>
<p>Para buscar texto en una cadena se utilizan las funciones <a href="http://php.net/preg_match">preg_match</a> y <a href="http://php.net/preg_match_all">preg_match_all</a>.<br />
La diferencia entre ambas es que <code class="linea">preg_match</code> detiene la búsqueda al encontrar la primera coincidencia, comportándose igual que <code class="linea">ereg</code>. La función <code class="linea">preg_match_all</code>, por otro lado, captura todas las coincidencias.</p>
<p>La sintaxis de <code class="linea">preg_match</code> es:<br />
<samp>int <strong>preg_match</strong> ( string <var>$patron</var> , string <var>$texto_en_el_que_buscar</var> [, array &#038;<var>$coincidencias</var> [, int <var>$banderas</var> [, int <var>$desplazamiento</var> ]]] )</samp></p>
<p>Dejaremos de lado los parámetros <var>$banderas</var> y <var>$desplazamiento</var>, que normalmente no se utilizan. El valor retornado por la función es 1 si se encontró una coincidencia, 0 en caso contrario. En caso de que el patrón contenga paréntesis, los datos se capturarán en el vector <var>$coincidencias</var>, de forma tal que el trozo de la cadena que coincide con el patrón se guarda en el índice cero, el trozo capturado por el primer juego de paréntesis se guardará en el índice 1, el trozo capturado por el segundo juego se guardará en el índice 2, y así sucesivamente.</p>
<h4>Ejemplo</h4>
<p>He aquí un ejemplo de uso:<br /> <br />
<code class="prettyprint">&lt;?php
define('ARCHIVO', 'ejemplo.txt');
define('PATRON', '#([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;(.+)&#034;&gt;(.*)&lt;/a&gt;&lt;br&gt;#U&#039;);
$archivo = file_get_contents( ARCHIVO );
$res = preg_match( PATRON, $archivo, $partes );
if ($res !== 0) {
            print_r($partes);
}</code></p>
<p>Este código carga el contenido del archivo y le aplica el patrón. El resultado será el siguiente:</p>
<p><samp>Array
(
    [0] => 2008 November 16:  &lt;a href=&#034;ap081116.html&#034;&gt;Anticrepuscular Rays Over Colorado&lt;/a&gt;&lt;br&gt;
    [1] => 2008
    [2] => November
    [3] => 16
    [4] => ap081116.html
    [5] => Anticrepuscular Rays Over Colorado
)</samp></p>
<p>Como puede verse, el índice cero del vector contiene la coincidencia completa, es decir, todo el texto que coincidió con el patrón. A partir del índice 1, se almacenan los trozos de texto que coincidieron con cada juego de paréntesis en el patrón.</p>
<p>El problema con esta función es que solamente captura la primera coincidencia. Por esto, en vez de devolver todos los enlaces del archivo, la salida de el código anterior contiene solamente la primera coincidencia, y no todas. Para capturar todas las coincidencias del patrón sobre un texto, se utiliza la función <code class="linea">preg_match_all</code>)</p>
<h4>Ejemplo 2: <code class="linea">preg_match_all</code></h4>
<p>El código necesario para utilizar esta función es exactamente igual al requerido para utilizar <code class="linea">preg_match</code>, solamente cambia el nombre de la función.<br />
<code class="prettyprint">&lt;?php
define('ARCHIVO', 'ejemplo.txt');
define('PATRON', '#([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;(.+)&#034;&gt;(.*)&lt;/a&gt;&lt;br&gt;#U&#039;);
$archivo = file_get_contents( ARCHIVO );
$res = preg_match( PATRON, $archivo, $partes );
if ($res !== 0) {
            print_r($partes);
}</code></p>
<p>Esta vez el resultado es bastante más extenso (aunque aquí aparece resumido):</p>
<p><samp>Array
(
    [0] => Array
        (
            [0] => 2008 November 16:  &lt;a href=&#034;ap081116.html&#034;>Anticrepuscular Rays Over Colorado&lt;/a>&lt;br>
            [1] => 2008 November 15:  &lt;a href=&#034;ap081115.html&#034;>Arp 273&lt;/a>&lt;br>
            [2] => 2008 November 14:  &lt;a href=&#034;ap081114.html&#034;>Fomalhaut b&lt;/a>&lt;br>
            [3] => 2008 November 13:  &lt;a href=&#034;ap081113.html&#034;>A Bubble in Cygnus&lt;/a>&lt;br>
            [4] => 2008 November 12:  &lt;a href=&#034;ap081112.html&#034;>Phoenix and the Holy Cow&lt;/a>&lt;br>
            [5] => 2008 November 11:  &lt;a href=&#034;ap081111.html&#034;>The Cosmic Web of the Tarantula Nebula&lt;/a>&lt;br>
            [6] => 2008 November 10:  &lt;a href=&#034;ap081110.html&#034;>Our Galaxy&#039;s Central Molecular Zone&lt;/a>&lt;br>
            [7] => 2008 November 09:  &lt;a href=&#034;ap081109.html&#034;>Two Black Holes Dancing in 3C 75&lt;/a>&lt;br>
            [8] => 2008 November 08:  &lt;a href=&#034;ap081108.html&#034;>On the Trail of 2008 TC3&lt;/a>&lt;br>
            [9] => 2008 November 07:  &lt;a href=&#034;ap081107.html&#034;>Cygnus Trio&lt;/a>&lt;br>
            [10] => 2008 November 06:  &lt;a href=&#034;ap081106.html&#034;>A Sharper View of a Hazy Giant&lt;/a>&lt;br>
            [11] => 2008 November 05:  &lt;a href=&#034;ap081105.html&#034;>Seventeen Hundred Kilometers Above Enceladus&lt;/a>&lt;br>
            [12] => 2008 November 04:  &lt;a href=&#034;ap081104.html&#034;>The Double Ring Galaxies of Arp 147 from Hubble&lt;/a>&lt;br>
            [13] => 2008 November 03:  &lt;a href=&#034;ap081103.html&#034;>A Spectacular Rayed Crater on Mercury&lt;/a>&lt;br>
            [14] => 2008 November 02:  &lt;a href=&#034;ap081102.html&#034;>Spicules: Jets on the Sun&lt;/a>&lt;br>
            [15] => 2008 November 01:  &lt;a href=&#034;ap081101.html&#034;>A Spectre in the Eastern Veil&lt;/a>&lt;br>
        )

    [1] => Array
        (
            [0] => 2008
            [...]
            [15] => 2008
        )

    [2] => Array
        (
            [0] => November
            [...]
            [15] => November
        )

    [3] => Array
        (
            [0] => 16
            [...]
            [15] => 01
        )

    [4] => Array
        (
            [0] => ap081116.html
            [...]
            [15] => ap081101.html
        )

    [5] => Array
        (
            [0] => Anticrepuscular Rays Over Colorado
            [...]
            [15] => A Spectre in the Eastern Veil
        )

)</samp></p>
<p>La salida de esta función es un tanto extraña. Uno esperaría recibir una matriz bidimensional en la que cada entrada fuera una coincidencia, y dentro de ella encontrar una entrada por cada trozo capturado, algo así:</p>
<p><samp>Array
(
    [0] => Array
        (
            [0] => 2008 November 16:  &lt;a href=&#034;ap081116.html&#034;>Anticrepuscular Rays Over Colorado&lt;/a>&lt;br>
            [1] => 2008
            [2] => November
            [3] => 16
            [4] => ap081116.html
            [5] => Anticrepuscular Rays Over Colorado
        )
)</samp></p>
<p>Sin embargo, lo que se devuelve es una matriz en la que la n-ésima entrada contiene cada trozo capturado por el n-ésimo paréntesis, de tal forma que si el nombre de la matriz es <var>$resultados</var>, <samp class="linea">$resultados[$n][$m]</samp> contiene el trozo de la m-ésima coincidencia que fue capturado por el n-ésimo paréntesis.</p>
<h3>Reemplazo de texto</h3>
<p>El reemplazo de texto se logra con <a href="http://php.net/preg_replace">preg_replace</a>. Se puede hacer uso de las <a href="http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias" title="Tipos de coincidencias y referencias">referencias</a> para vincular al contenido capturado por los paréntesis.</p>
<p>Por ejemplo, puede sustituirse el enlace por un listado del día y el título:</p>
<p><code class="prettyprint"><?php
define('ARCHIVO', 'ejemplo.txt');
define('PATRON', '#([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href="(.+)">(.+)&lt;/a>#U&#039;);
$archivo = file_get_contents( ARCHIVO );
$res = preg_replace( PATRON, &#039;Imagen del día \\3 de \\2: \\5&#039;, $archivo );
echo $res;</code></p>
<p><code>Imagen del día 16 de November: Anticrepuscular Rays Over Colorado
Imagen del día 15 de November: Arp 273
Imagen del día 14 de November: Fomalhaut b
Imagen del día 13 de November: A Bubble in Cygnus
Imagen del día 12 de November: Phoenix and the Holy Cow
Imagen del día 11 de November: The Cosmic Web of the Tarantula Nebula
Imagen del día 10 de November: Our Galaxy's Central Molecular Zone
Imagen del día 09 de November: Two Black Holes Dancing in 3C 75
Imagen del día 08 de November: On the Trail of 2008 TC3
Imagen del día 07 de November: Cygnus Trio
Imagen del día 06 de November: A Sharper View of a Hazy Giant
Imagen del día 05 de November: Seventeen Hundred Kilometers Above Enceladus
Imagen del día 04 de November: The Double Ring Galaxies of Arp 147 from Hubble
Imagen del día 03 de November: A Spectacular Rayed Crater on Mercury
Imagen del día 02 de November: Spicules: Jets on the Sun
Imagen del día 01 de November: A Spectre in the Eastern Veil</code></p>
<h3>División de cadenas</h3>
<p>Para dividir cadenas PHP incluye la función <a href="http://php.net/explode">explode()</a>, que divide una cadena en trozos utilizando otra cadena (que se le pasa como parámetro) como separador.<br />
El problema con <code class="linea">explode</code> es que toma una cadena fija, por lo que en ocasiones puede no tener la flexibilidad necesaria.</p>
<p>La función <a href="http://php.net/preg_split">preg_split()</a> funciona de forma similar a <code class="linea">explode</code>, pero en vez de utilizar una cadena fija como separador utiliza una expresión regular.</p>
<p>Cualquiera que haya utilizado la función <code class="linea">explode</code> sabe cómo se utiliza <code class="linea">preg_split</code>, ya que ambas se utilizan de forma similar. Recomiendo ver las páginas del manual de ambas funciones para obtener ejemplos de uso.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/php/177-expresiones-regulares-con-php-perl/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Consejos para evitar el SPAM</title>
		<link>http://elcodiguero.com/general/183-consejos-para-evitar-el-spam</link>
		<comments>http://elcodiguero.com/general/183-consejos-para-evitar-el-spam#comments</comments>
		<pubDate>Mon, 17 Nov 2008 18:59:57 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos varios]]></category>

		<guid isPermaLink="false">http://elcodiguero.com/?p=183</guid>
		<description><![CDATA[Introducción
El spam, o correo basura es sin duda alguna la parte más molesta de trabajar con correo electrónico.
Otros términos que se usan frecuentemente son UCE (siglas en inglés de Correo electrónico comercial no solicitado) o UBE (siglas en inglés de Correo electrónico masivo no solicitado).
La peor parte del correo basura es que los costos para [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción</h2>
<p>El <q xml:lang="en">spam</q>, o <q>correo basura</q> es sin duda alguna la parte más molesta de trabajar con correo electrónico.<br />
Otros términos que se usan frecuentemente son <acronym xml:lang="en" title="Unsolicited Commercial E-mail">UCE</acronym> (siglas en inglés de <q>Correo electrónico comercial no solicitado</q>) o <acronym xml:lang="en" title="Unsolicited Bulk E-mail">UBE</acronym> (siglas en inglés de <q>Correo electrónico masivo no solicitado</q>).<br />
La peor parte del correo basura es que los costos para quien lo envía es casi nulo. Quien debe asumir el costo de transporte, almacenamiento y filtrado (automático y manual) de los mensajes es el proveedor de correo del destinatario. También hay que considerar la pérdida de tiempo que insume el filtrado manual de los mensajes, sobretodo cuando la cuenta de correo ha sido comprometida y recibe grandes cantidades de basura.</p>
<p>Si bien los proveedores de correo tienen cada vez mejores filtros automáticos, que nos evitan tener que eliminar manualmente la mayoría de los mensajes basura, aún hay muchas precauciones y buenas prácticas que uno puede tomar para evitar que la casilla se inunde.<br />
Sobretodo es importante conocer y difundir las mejores prácticas, y enseñar a los novatos a reconocer las amenazas que el <q xml:lang="en">spam</q> trae consigo (fraudes, estafas, venta de productos ilegales, etc). Aunque parezca increíble, hay mucha gente sin experiencia que cae con facilidad en estos engaños.</p>
<h2>¿Cómo obtienen las direcciones de correo los <q xml:lang="en">spammers</q></h2>
<h3>Direcciones de correo visibles en la web</h3>
<p>Los <q xml:lang="en">spammers</q> (aquellos quienes envían el correo basura) utilizan varios métodos para recolectar nuestras direcciones de correo. Uno de ellos es el uso de <q>robots</q> que recorren las páginas web buscando direcciones. Es decir, si mi dirección de correo electrónico está públicamente visible en una página web, tarde o temprano un robot <q xml:lang="en">spammer</q> la encontrará.</p>
<h3>Cadenas</h3>
<p>Por regla general las cadenas deberían eliminarse sin prestarles mucha atención. Sin embargo, las personas suelen reenviarlas a todos sus contactos, lo cual provoca que luego de 4 o 5 reenvíos el cuerpo del mensaje contenga decenas de direcciones. Si de casualidad el mensaje sigue reenviándose, podría caer eventualmente en poder de un <q xml:lang="en">spammer</q>, muchas veces debido a <a href="http://es.wikipedia.org/wiki/Spam#Troyanos_y_ordenadores_zombis">troyanos u otra clase de programas maliciosos</a>.</p>
<p>Sin entrar en los medios técnicos (que deberían estar a cargo de los administradores de los servidores de correo, no de los usuarios), aún hay algunas prácticas que pueden seguirse para evitar el daño causado por el correo basura.</p>
<h2>Evitar el <q xml:lang="en">spam</q> antes de que llegue</h2>
<p>La mejor manera de evitar el correo basura es <strong>evitar que nuestra dirección de correo electrónico termine en la base de datos</strong> de algún delincuente (en muchos países del mundo el envío de <q xml:lang="en">spam</q> es un delito).</p>
<p>Una buena práctica es <strong>tener al menos dos cuentas diferentes</strong>, una para uso personal y otra para suscripciones a sitios web. Con esto se expone solamente una de las cuentas, que además como no se utiliza para temas personales se puede reemplazar de forma sencilla si comienza a recibir gran cantidad de mensajes basura.</p>
<p>En conjunción con esta práctica, es importante dejar la dirección de correo solamente en sitios medianamente confiables, ya que uno nunca sabe qué puede hacer el creador del sitio con la información almacenada.</p>
<p>Otro punto a considerar es el de las cadenas, como se mencionó arriba. Todos tenemos algún conocido o amigo que no conoce (o pasa por alto) el problema que conlleva el reenviar correo incluyendo todas las direcciones en el campo <q>Para</q>, y sin borrar las cabeceras del mensaje que quiere reenviar.<br />
Entonces, para evitar que nuestra cuenta termine en alguna máquina infectada por un troyano (que a su vez envíe la información al servidor de un <q xml:lang="en">spammer</q>), es importante explicarle a la gente lo importante que es NO reenviar cadenas, o si se reenvían hacerlo con los cuidados necesarios: enviando solamente el contenido y no las cabeceras de los mensajes anteriores, y poniendo las direcciones en el campo <q>CCO</q> (copia oculta) en vez de en <q>CC</q> para que así cada destinatario no vea las direcciones de los demás.</p>
<h2>Qué hacer cuando ya se está recibiendo correo basura</h2>
<p>La mayoría de las veces la precaución no es suficiente: la cuenta comienza a recibir correo basura de todas formas.<br />
La estrategia en este punto deja de ser unicamente la protección de la cuenta (aunque claramente esto se debe seguir haciendo) para pasar a ser el pretender que la cuenta no existe. Esto es, cualquier respuesta que se envíe a los <q xml:lang="en">spammers</q> solamente logrará que nos llegue aún más basura. Por este motivo nunca, bajo ningún concepto, se debe responder a ningún correo no solicitado.</p>
<p>Pero no responder no es suficiente para <q>fingir</q> que la cuenta no existe: el cliente de correo que usemos nos puede traicionar (Thunderbird, Outlook Express, o incluso los clientes web de Gmail o Yahoo). Por esto se recomienda NO abrir mensajes sospechosos, o abrirlos únicamente si el cliente de correo está configurado para mostrarlos en <q>modo texto</q>.<br />
El motivo es sencillo: si el cliente de correo admite formato de texto, admitirá imágenes y otras clases de archivos externos. Es muy sencillo incluir un código extra para que a la vez que se envía la petición para obtener esa imagen o archivo externo, se envíe una confirmación de que la cuenta de correo es válida.</p>
<p>No deberíamos tampoco hacer clic en ningún enlace que el correo incluya. En el pasado ha habido fallos en todos los clientes de correo y navegadores, que permiten ir hacia un sitio falseando su dirección. Es decir, cuando uno piensa que está en el sitio de su banco, al que llegó a través de un enlace en un correo, bien podría estar en realidad en un sitio fraudulento.</p>
<p>Una de las reglas generales que siempre deberían seguirse es: <strong>si el mensaje no fue solicitado, proceder con precaución</strong>. No importa si parece venir de una empresa o sitio web conocido, las direcciones de correo electrónico son fácilmente falseables. Incluso algo tan confiable a primera vista como <q>soporte@microsoft.com</q> podría ser en realidad un fraude.</p>
<p>Afortunadamente para nosotros los hispanohablantes, la mayoría del correo basura se envía en inglés. Por lo que si no tenemos ningún conocido que hable en inglés, se puede descartar con seguridad cualquier correo que no esté en español.</p>
<h3>Nunca comprar</h3>
<p>Hay que reconocerlo, a veces las ofertas de lo que se vende son interesantes. Pero con el bajo costo que tiene enviar un correo, una sola compra seguramente compense el envío de millones de mensajes no solicitados. Por este motivo es fundamental no comprar nada que se oferte a través de <q xml:lang="en">spam</q>, ya que las ventas que se consiguen son el principal motivo para enviarlo (y eso sin contar que en la mayoría de los casos no se trata de comerciantes sino de estafadores, por lo que solamente terminaríamos perdiendo el dinero).</p>
<h2>Comentario final</h2>
<p>A pesar de todo lo comentado, hay que saber reconocer cuando nos han vencido: si la cuenta de correo recibe demasiada basura, no queda otra opción que reemplazarla. Por esto es importante tener una cuenta para asuntos personales y otra para lo demás, es de suponer que la cuenta utilizada solamente para asuntos personales estará más protegida, menos gente la conocerá.</p>
<p>Lamentablemente, debido a los delincuentes una herramienta tan útil como el correo electrónico a veces se vuelve inusable. Es imprescindible entonces poner todos un granito de arena para evitar que la plaga se vuelva aún peor.</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/Spam">Wikipedia: Spam</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/general/183-consejos-para-evitar-el-spam/feed</wfw:commentRss>
		</item>
		<item>
		<title>Expresiones regulares con PHP - POSIX</title>
		<link>http://elcodiguero.com/php/155-expresiones-regulares-con-php-posix</link>
		<comments>http://elcodiguero.com/php/155-expresiones-regulares-con-php-posix#comments</comments>
		<pubDate>Tue, 04 Nov 2008 13:45:17 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=155</guid>
		<description><![CDATA[Nota: Como texto a analizar se utilizará esta página, que es un trozo conveniente de esta otra. Se eligió este texto por ser repetitivo y sencillo de comprender. Para analizarlo, se utilizará el siguiente patrón:
([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &#60;a href=&#034;([^"]+)&#034;&#62;(.*?)&#60;/a&#62;&#60;br&#62;
Introducción
PHP incluye soporte para expresiones regulares en el núcleo mismo del lenguaje, no se requieren extensiones [...]]]></description>
			<content:encoded><![CDATA[<p class="nota">Nota: Como <q>texto a analizar</q> se utilizará <a href="/archivos/ejemplo.txt">esta página</a>, que es un trozo <q>conveniente</q> de <a href="http://antwrp.gsfc.nasa.gov/apod/archivepix.html">esta otra</a>. Se eligió este texto por ser repetitivo y sencillo de comprender. Para analizarlo, se utilizará el siguiente patrón:<br />
<code>([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;([^"]+)&#034;&gt;(.*?)&lt;/a&gt;&lt;br&gt;</code></p>
<h2>Introducción</h2>
<p><a href="http://www.php.net">PHP</a> incluye soporte para expresiones regulares en el núcleo mismo del lenguaje, no se requieren extensiones para habilitarlo. Se soporta por defecto tanto la sintaxis <a href="http://es.wikipedia.org/wiki/POSIX" title="Portable Operating System Interface">POSIX</a> (funciones <em>ereg*</em>) como la sintaxis PERL (funciones <em>preg*</em>).<br /> <br />
Tradicionalmente se prefiere el uso de la sintaxis de Perl, en el entendido de que las funciones correspondientes tienen un mejor rendimiento que sus homólogas POSIX; sin embargo esto varía caso a caso según el tipo de patrón que se utilice. Si el rendimiento es crítico, se deben probar ambos tipos de patrones y comparar sus resultados.</p>
<p>Como mencionaba en una parte anterior de esta serie (<a href="http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias" title="Tipos de coincidencias y referencias">Tipos de coincidencias y referencias</a>), las funciones de expresiones regulares se separan en tres grupos: coincidencia de texto, reemplazo de texto, y separación de cadenas; siendo esta última la opción menos usada.</p>
<h2>Funciones de Expresiones Regulares POSIX</h2>
<p>Las funciones que PHP provee para utilizar expresiones regulares con sintaxis POSIX son:</p>
<ul>
<li><a href="http://php.net/ereg">ereg</a></li>
<li><a href="http://php.net/eregi">eregi</a></li>
<li><a href="http://php.net/ereg_replace">ereg_replace</a></li>
<li><a href="http://php.net/eregi_replace">eregi_replace</a></li>
<li><a href="http://php.net/split">split</a></li>
<li><a href="http://php.net/spliti">spliti</a></li>
</ul>
<h3>Coincidencia de texto</h3>
<p><a href="http://php.net/ereg">ereg</a> y <a href="http://php.net/eregi">eregi</a> son las funciones encargadas de comparar una cadena de texto contra un patrón. La diferencia entre ambas es que <code class="linea">eregi</code> no diferencia entre mayúsculas y minúsculas. Esta característica la hace un poco más práctica, a la vez que un poco más lenta.</p>
<p>La sintaxis de ambas funciones es:<br /> <br />
<samp>int ereg ( string <var>$patron</var> , string <var>$cadena</var> [, array <var>$partes</var> ] )</samp></p>
<p>El valor retornado es <q>un valor verdadero</q> si se encontró alguna coincidencia, o <q>falso</q> si no se encontró ninguna. En caso de que el patrón contenga paréntesis, los datos se capturarán en el vector <var>$partes</var>, de forma tal que el trozo de la cadena que coincide con el patrón se guarda en el índice cero, el trozo capturado por el primer juego de paréntesis se guardará en el índice 1, el trozo capturado por el segundo juego se guardará en el índice 2, y así sucesivamente.</p>
<h4>Ejemplo</h4>
<p>He aquí un ejemplo de uso:<br /> <br />
<code class="prettyprint">&lt;?php
define('ARCHIVO', 'ejemplo.txt');
define('PATRON', '([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;([^"]+)&#034;&gt;([^<]+)&lt;/a&gt;&lt;br&gt;&#039;);
$archivo = file_get_contents( ARCHIVO );
$res = ereg( PATRON, $archivo, $partes ); 

if ($res !== false) {
    print_r($partes);
}
?&gt;</code></p>
<p>Este código carga el contenido del archivo y le aplica el patrón. El resultado será el siguiente:</p>
<p><code>Array
(
    [0] => 2008 November 16:  <a href="ap081116.html">Anticrepuscular Rays Over Colorado</a>
    [1] => 2008
    [2] => November
    [3] => 16
    [4] => ap081116.html
    [5] => Anticrepuscular Rays Over Colorado
)</code></p>
<p>Como puede verse, el índice cero del vector contiene la coincidencia completa, es decir, todo el texto que coincidió con el patrón. A partir del índice 1, se almacenan los trozos de texto que coincidieron con cada juego de paréntesis en el patrón.</p>
<p>El problema con esta función es que solamente captura la primera coincidencia. Por esto, en vez de devolver todos los enlaces del archivo, la salida de el código anterior contiene solamente la primera coincidencia, y no todas. Este es otro de los motivos por los cuales se utilizan las funciones compatibles con Perl: una de ellas sirve para capturar todas las coincidencias del patrón sobre un texto (<a href="http://www.php.net/preg_match_all">preg_match_all</a>)</p>
<h3>Reemplazo de texto</h3>
<p>El reemplazo de texto se logra con <a href="http://php.net/ereg_replace">ereg_replace</a>. Se puede hacer uso de las <a href="http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias" title="Tipos de coincidencias y referencias">referencias</a> para vincular al contenido capturado por los paréntesis.</p>
<p>Por ejemplo, puede sustituirse el enlace por un listado del día y el título:</p>
<p><code class="prettyprint">define('ARCHIVO', 'ejemplo.txt');
define('PATRON', '([0-9]{4}) ([A-Za-z]+) ([0-9]{2}):  &lt;a href=&#034;([^"]+)&#034;&gt;([^&lt;]+)&lt;/a&gt;&#039;);
$archivo = file_get_contents( ARCHIVO );
$res = ereg_replace( PATRON, &#039;Imagen del día \\3 de \\2: \\5&#039;, $archivo );</code></p>
<p><code>Imagen del día 16 de November: Anticrepuscular Rays Over Colorado
Imagen del día 15 de November: Arp 273
Imagen del día 14 de November: Fomalhaut b
Imagen del día 13 de November: A Bubble in Cygnus
Imagen del día 12 de November: Phoenix and the Holy Cow
Imagen del día 11 de November: The Cosmic Web of the Tarantula Nebula
Imagen del día 10 de November: Our Galaxy's Central Molecular Zone
Imagen del día 09 de November: Two Black Holes Dancing in 3C 75
Imagen del día 08 de November: On the Trail of 2008 TC3
Imagen del día 07 de November: Cygnus Trio
Imagen del día 06 de November: A Sharper View of a Hazy Giant
Imagen del día 05 de November: Seventeen Hundred Kilometers Above Enceladus
Imagen del día 04 de November: The Double Ring Galaxies of Arp 147 from Hubble
Imagen del día 03 de November: A Spectacular Rayed Crater on Mercury
Imagen del día 02 de November: Spicules: Jets on the Sun
Imagen del día 01 de November: A Spectre in the Eastern Veil</code></p>
<h3>División de cadenas</h3>
<p>Para dividir cadenas PHP incluye la función <a href="http://php.net/explode">explode()</a>, que divide una cadena en trozos utilizando otra cadena (que se le pasa como parámetro) como separador.<br />
El problema con <code class="linea">explode</code> es que toma una cadena fija, por lo que en ocasiones puede no tener la flexibilidad necesaria.</p>
<p>La función <a href="http://php.net/split">split()</a> (y <a href="http://php.net/split">spliti()</a>, la versión que no distingue entre mayúsculas y minúsculas) funciona de forma similar a <code class="linea">explode</code>, pero en vez de utilizar una cadena fija como separador utiliza una expresión regular.</p>
<p>Cualquiera que haya utilizado la función <code class="linea">explode</code> sabe cómo se utiliza <code class="linea">split</code>, ya que ambas se utilizan de forma similar. Recomiendo ver las páginas del manual de ambas funciones para obtener ejemplos de uso.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/php/155-expresiones-regulares-con-php-posix/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Uruguay: Ley de protección de datos personales</title>
		<link>http://elcodiguero.com/varios/158-uruguay-ley-de-proteccion-de-datos-personales</link>
		<comments>http://elcodiguero.com/varios/158-uruguay-ley-de-proteccion-de-datos-personales#comments</comments>
		<pubDate>Wed, 22 Oct 2008 16:17:24 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Opiniones y comentarios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=158</guid>
		<description><![CDATA[Hace algunos días asistí a una charla organizada por la empresa Security Advisor sobre la recientemente aprobada Ley de protección de datos personales: Ley Nº 18.331 PROTECCIÓN DE DATOS PERSONALES Y ACCIÓN DE &#034;HABEAS DATA&#034;.
Fue creada en conjunto por el Ministerio de Economía y Finanzas, el Instituto de Derecho Informático de la Facultad de Derecho [...]]]></description>
			<content:encoded><![CDATA[<p>Hace algunos días asistí a una charla organizada por la empresa <a href="http://www.sadvisor.com">Security Advisor</a> sobre la recientemente aprobada Ley de protección de datos personales: <a href="http://www.parlamento.gub.uy/leyes/AccesoTextoLey.asp?Ley=18331">Ley Nº 18.331 PROTECCIÓN DE DATOS PERSONALES Y ACCIÓN DE &#034;HABEAS DATA&#034;.</a><br />
Fue creada en conjunto por el <a href="http://mef.gub.uy">Ministerio de Economía y Finanzas</a>, el Instituto de Derecho Informático de la <a href="http://www.fder.edu.uy/">Facultad de Derecho</a> y la <a href="http://www.agesic.gub.uy">Agencia para el Desarrollo de la Gestión Electrónica y la Sociedad de la Información y el Conocimiento (AGESIC)</a>.</p>
<p>Se elaboró tomando como base a la <a href="http://es.wikipedia.org/wiki/Ley_Orgánica_de_Protección_de_Datos_de_Carácter_Personal_de_España">Ley Orgánica de Protección de Datos de Carácter Personal de España</a> (conocida como LOPD), uno de sus objetivos es lograr que Uruguay sea considerado por la UE como un país con <q>nivel adecuado</q> de protección de datos, para así facilitar las relaciones entre Uruguay y la UE.</p>
<h2>Almacenamiento de datos</h2>
<p>Esta nueva ley impone controles al almacenamiento de datos personales cualquiera sea el fin. Se obliga a aquellas entidades que requieran almacenamiento de información personal a que registren sus bases de datos, y a no guardar información personal sin consentimiento <q>previo e informado</q> del titular de esos datos; esto es, el fin para el que se guardan los datos debe estar determinado y debe ser informado al titular.<br />
La ley define un conjunto de datos como <q>datos sensibles</q> que no pueden ser almacenados:</p>
<blockquote cite="http://www.parlamento.gub.uy/leyes/AccesoTextoLey.asp?Ley=18331"><p>Dato sensible: datos personales que revelen origen racial y étnico, preferencias políticas, convicciones religiosas o morales, afiliación sindical e informaciones referentes a la salud o a la vida sexual.</p></blockquote>
<p>Se menciona también que los datos que se guardan deben estar relacionados con el giro de actividad de la empresa, y que deben ser
<p>proporcionales</q> al fin (si para la actividad de la empresa se requiere nombre y teléfono, la empresa no puede almacenar además dirección postal, correo-e, licencia de conducir, etc).</p>
<p>Por otro lado, se permite que la base de datos no tenga que registrarse si solamente contiene nombre, nacionalidad, fecha de nacimiento y cédula de identidad (basicamente, se excluyen los datos que aparecen en el documento).</p>
<h2>Reglamentación</h2>
<p>Actualmente se está trabajando en una reglamentación para la ley. Esta reglamentación se hace necesaria en tanto que se puede ver que la intención fue crear una ley amplia que permitiese abarcar la mayor cantidad de casos posibles.</p>
<p>La ley define:</p>
<blockquote cite="http://www.parlamento.gub.uy/leyes/AccesoTextoLey.asp?Ley=18331"><p>Bases de Datos: indistintamente, designan al conjunto organizado de datos personales que sean objeto de tratamiento o procesamiento, electrónico o no, cualquiera que fuere la modalidad de su formación, almacenamiento, organización o acceso.</p></blockquote>
<p>y</p>
<blockquote cite="http://www.parlamento.gub.uy/leyes/AccesoTextoLey.asp?Ley=18331"><p>Dato personal: información de cualquier tipo referida a personas físicas o jurídicas determinadas o determinables.</p></blockquote>
<p>Esto hace que una habitación llena de biblioratos sea también una base de datos, y por lo tanto deba registrarse.<br />
De la definición de dato personal se deriva que, en tanto que el dato hace a la persona <q>determinable</q>, se entiende que una foto o una grabación en video (o de la voz) de la persona es un dato personal.</p>
<p>La reglamentación es necesaria en tanto que, con estas definiciones, el estado legal de las cámaras de vigilancia de los bancos es dudoso (por poner un ejemplo de muchos que se pueden pensar).</p>
<h2>Exclusiones</h2>
<p>La ley no aplica para datos que una empresa obtenga a partir de una relación contractual; por ejemplo las empresas podrán tener bases de datos con información sobre sus empleados sin tener que registrarlas. Otro ejemplo puede ser un contrato de servicios de telefonía, o de servicios médicos.</p>
<p>La ley tampoco aplica para aquellos datos cuyo tratamiento esté regido por otras normas específicas, como es el caso de la información crediticia, el historial penal, o la historia clínica de una persona. Esto implica que las bases de datos que contengan esta clase de información tampoco necesitan ser registradas, ni se requiere obtener autorización del usuario. Sí podría aplicarse en algunos casos, y esto dependerá de la regulación que se de a la ley, el principio de proporcionalidad (no almacenar más información de la necesaria).</p>
<h2>Pasos siguientes</h2>
<p>Se prevé un plazo de 1 año desde la fecha de aprobación para que las empresas que cuentan con bases de datos comprendidas en la ley, se adecúen a la misma.<br />
Por lo pronto, el órgano de control encargado de recibir los registros de las bases de datos aún no existe, y la reglamentación que se mencionaba antes está en proceso de creación.<br />
En lo personal me pareció una buena ley, bien estructurada y respetuosa de los derechos de los ciudadanos para con su información personal. Habrá que ver si la reglamentación que se propondrá continúa en la misma línea.</p>
<h4 class="relacionados">Presentaciones de la charla</h4>
<ul>
<li>Charla de apertura, agenda y cierre de Ing. Leonardo Berro , Director de Security Advisor<br />
<a href="http://www.sadvisor.com/descargas/Agenda.pdf"><q>Organizaciones Seguras y aportes para la seguridad de datos sensibles en la Empresa</q></a></li>
<li>Charla a cargo del Sr.  Federico Monteverde, Asesor de Agesic<br />
<a href="http://www.sadvisor.com/descargas/Present1.pdf"><q>Importancia de proteger nuestros datos personales, desde los antecedentes a la futura reglamentación</q></a></li>
<li>Charla a cargo de la Lic. Déborah Rivas y de la Dra. Giovanna Lorenzi, Consultora de KPMG Uruguay (IT Advisory Legal)<br />
<a href="http://www.sadvisor.com/descargas/Present2.pdf"><q>Quo Vadis? … Hacia dónde vas América Latina?</q></a></li>
<li>Charla a cargo de la Ing. Cristina Ledesma, Integrante de la CD de la ISACA<br />
<a href="http://www.sadvisor.com/descargas/Present3.pdf"><q>Fortaleciendo las estrategias hacia la aplicabilidad, que tan lejos (o cerca) estamos?</q></a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/varios/158-uruguay-ley-de-proteccion-de-datos-personales/feed</wfw:commentRss>
		</item>
		<item>
		<title>Opera MAMA: ¿de qué está hecha la Web?</title>
		<link>http://elcodiguero.com/varios/143-opera-mama-%c2%bfde-que-esta-hecha-la-web</link>
		<comments>http://elcodiguero.com/varios/143-opera-mama-%c2%bfde-que-esta-hecha-la-web#comments</comments>
		<pubDate>Mon, 20 Oct 2008 18:02:43 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Opiniones y comentarios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=143</guid>
		<description><![CDATA[Hace unos días el equipo de QA de Opera presentó el proyecto MAMA (Metadata Analysis and Mining Application). Este proyecto de Opera es, según la nota de presentación, un motor de búsqueda de estructura, en vez de contenido.
El objetivo de MAMA es la recopilación de datos y el análisis de la estructura de los sitios [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días el <a href="http://my.opera.com/operaqa/blog/">equipo de <acronym title="Quality Assurance">QA</acronym></a> de <a href="http://www.opera.com">Opera</a> presentó <a href="http://my.opera.com/operaqa/blog/2008/10/15/mama-what-is-the-web-made-of">el proyecto MAMA (<span xml:lang="en">Metadata Analysis and Mining Application</span>)</a>. Este proyecto de Opera es, según la nota de presentación, <q>un motor de búsqueda de estructura, en vez de contenido</q>.</p>
<p>El objetivo de MAMA es la recopilación de datos y el análisis de la estructura de los sitios web. De esta forma, se pueden contestar preguntas como qué tecnologías son más populares, qué tipo <acronym title="Multipurpose Internet Mail Extensions">MIME</acronym> se utiliza, qué porcentaje de sitios incluye archivos de Javascript o <acronym title="Cascade Style Sheets">CSS</acronym>, o qué porcentaje de sitios contiene HTML válido.<br />
Incluso puede ayudar a los equipos de desarrollo de los navegadores para saber en qué clase de fallos deben concentrarse y qué tecnologías deben implementar.</p>
<p>Junto con el anuncio oficial, se publicaron dos estudios de los muchos a los que puede dar lugar la información recopilada por MAMA: <strong>¿Cómo es la página web promedio?</strong> y <strong>¿Qué porcentaje de páginas web utiliza código válido?</strong>.</p>
<h2>La página web promedio</h2>
<p><a href="http://dev.opera.com/articles/view/mama-key-findings/">http://dev.opera.com/articles/view/mama-key-findings/</a><br />
Este estudio contiene datos interesantes, por ejemplo menciona que la página promedio no tiene <samp class="linea">DOCTYPE</samp>, y que cuando se utiliza uno se utiliza <strong>HTML 4.x Transicional</strong>. Es fácil concluir de esto que la mayoría de las páginas se analiza en modo &#034;permisivo&#034; (<span xml:lang="en">quirks</span>).<br />
Lamentablemente la página promedio contiene al menos 1 elemento <strong>FONT</strong>, con los atributos <samp class="linea">color</samp>, <samp class="linea">face</samp> y <samp class="linea">size</samp>.</p>
<p>En cuanto a CSS, la página promedio contiene al menos un elemento <samp class="linea">STYLE</samp> y una referencia a un archivo externo (que muy probablemente se llame <q>style.css</q>) de 8,5 KB. Al parecer el uso mayoritario de CSS sigue siendo el control de fuentes.</p>
<p>Se menciona que el promedio de imágenes por página es 23, el de enlaces 38 (con al menos 1 que se abre en una nueva página), y el de etiquetas <samp class="linea">META</samp> 3 (<samp class="linea">Content-Type</samp>, <samp class="linea">description</samp> y <samp class="linea">keywords</samp>).</p>
<p>Se utilizan en promedio 2,5 archivos Javascript externos, con un tamaño sumado de 26 KB. Eso se suma a los 3,6 elementos <samp class="linea">SCRIPT</samp> y a los 19,2 manejadores de eventos declarados en la página.</p>
<h2>HTML válido</h2>
<p><a href="http://dev.opera.com/articles/view/mama-w3c-validator-research-2/">http://dev.opera.com/articles/view/mama-w3c-validator-research-2/</a><br />
Se puede ver que solamente el 4,13% de las páginas analizadas por MAMA contienen HTML válido. Según el estudio, este número crece lentamente, pero es claro que aún es ridículamente bajo.</p>
<p>Se detalla el porcentaje de páginas con HTML válido según el uso de otras características. Podemos enterarnos que solamente el 1,44% de las páginas que utilizan marcos (frames) contienen HTML válido, el número se eleva a 4,72% si la página utiliza CSS.<br />
Se muestra también un dato curioso: el número de páginas válidas alojadas en servidores <a href="http://httpd.apache.org/">Apache</a> casi duplica a las páginas válidas alojadas en servidores <a href="http://www.iis.net/">IIS</a> (5,38% contra 2,80%)</p>
<p>Otro análisis tiene que ver con los editores y los CMS, con datos obtenidos analizando las etiquetas META <q>Generator</q>.<br />
En cuanto a editores, podemos saber que el 81% de las páginas creadas con <a href="http://www.apple.com/ilife/iweb/">Apple iWeb</a> son válidas, mientras que en el otro extremo se ubica <a href="http://www.microsoft.com/frontpage/">FrontPage</a>, con 0,60%.<br />
Y en lo que respecta a gestores de contenido, los resultados varían entre el 0,30% (<a href="http://www.blogger.com">Blogger</a>) y el 12,74% (<a href="http://www.typo3.org">Typo3</a>)</p>
<p>Decepcionante es descubrir que <strong>1 de cada 2 páginas que muestran un botón de <q>HTML válido</q>, en realidad contienen errores de validación</strong>. Queda pendiente la pregunta, que obviamente un analizador automático no puede contestar, de cuál es el motivo de esos botones. ¿Se colocaron porque sí? ¿se colocaron en un momento en el que la página era válida y luego el código de la página cambió?</p>
<p>El estudio contiene muchos otros datos interesantes, como por ejemplo qué codificación de caracteres se utiliza más (iso-8859-1 seguido por UTF-8) o cuáles son los errores de validación más comunes.<br />
En mi opinión es un artículo muy interesante, al menos para obtener un pantallazo de la situación actual.</p>
<p>Es una lástima que solamente esté en inglés, pero seguramente los traductores automáticos pueden hacer un trabajo decente para aquellos que lo necesitan.</p>
<p>Un detalle a recordar en todo momento es que la muestra del estudio es bastante reducida, se analizaron 3,5 millones de páginas mientras que la Web actual contiene varias decenas de miles de millones.</p>
<p>Solamente se han publicado algunos de los estudios que se planea publicar, pero lo que se ve ya hace de MAMA un reflejo interesante de la Web.</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://dev.opera.com/articles/view/mama/">MAMA: What is the Web made of?</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/varios/143-opera-mama-%c2%bfde-que-esta-hecha-la-web/feed</wfw:commentRss>
		</item>
		<item>
		<title>Diferencias de sintaxis entre POSIX y Perl</title>
		<link>http://elcodiguero.com/programacion/111-diferencias-de-sintaxis-entre-posix-y-perl</link>
		<comments>http://elcodiguero.com/programacion/111-diferencias-de-sintaxis-entre-posix-y-perl#comments</comments>
		<pubDate>Sun, 12 Oct 2008 23:46:25 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=111</guid>
		<description><![CDATA[En partes anteriores se menciona varias veces que existen diferencias de sintaxis entre las expresiones regulares POSIX y las expresiones regulares compatibles con Perl.
Hasta ahora se han descrito únicamente las expresiones regulares POSIX. El motivo para esto es que la diferencia entre Perl y POSIX no radica en cuantificadores, metacaracteres y clases, sino que radica [...]]]></description>
			<content:encoded><![CDATA[<p>En partes anteriores se menciona varias veces que existen diferencias de sintaxis entre las expresiones regulares <a href="http://es.wikipedia.org/wiki/POSIX">POSIX</a> y las expresiones regulares compatibles con Perl.</p>
<p>Hasta ahora se han descrito únicamente las expresiones regulares POSIX. El motivo para esto es que la diferencia entre Perl y POSIX no radica en cuantificadores, metacaracteres y clases, sino que radica en algo que no tiene relación directa con el patrón mismo.<br />
Estas diferencias son basicamente dos: los delimitadores y los modificadores. Fuera de estos dos puntos un patrón POSIX es perfectamente válido para Perl.<br />
Entre los lenguajes que utilizan expresiones regulares compatibles con Perl se encuentran:</p>
<ul>
<li>PHP (que puede trabajar con ambas sintaxis)</li>
<li>Javascript</li>
<li>Java</li>
<li>Perl (obviamente)</li>
</ul>
<p>(y seguramente una miríada de lenguajes más).</p>
<h2>Delimitadores</h2>
<p>El patrón <code>[a-z]</code> es perfectamente válido para POSIX. No requiere ningún extra, es completo.<br />
Sin embargo, el mismo patrón escrito con sintaxis compatible con Perl, debe escribirse como:<br />
<code>/[a-z]/</code></p>
<p>Cuando se utiliza la sintaxis de Perl, el patrón completo debe ir delimitado por un caracter &#034;/&#034; al comienzo y al final. Esto implica por supuesto que cualquier barra / que forme parte del patrón mismo debe escaparse con la contrabarra \ (quedando &#034;\/&#034; en vez de &#034;/&#034;).</p>
<p>Algo interesante a recordar es que si bien por defecto se utiliza la barra <strong>/</strong>, en realidad se puede utilizar cualquier caracter especial como delimitador.<br />
En este contexto &#034;caracter especial&#034; significa un caracter que no es un número ni una letra, aunque no todos están permitidos. Los que se usan comunmente son <strong>#</strong>, <strong>@</strong> y <strong>!</strong>.<br />
Por ejemplo, los siguientes patrones son completamente equivalentes:<br />
<code>/[a-z]\/[0-9]/</code><br />
<code>@[a-z]/[0-9]@</code><br />
<code>#[a-z]/[0-9]#</code><br />
<code>![a-z]/[0-9]!</code></p>
<p>Nótese cómo gracias a que / no se utiliza como delimitador, solamente en el primer ejemplo se requiere escapar la barra que separa [a-z] y [0-9].</p>
<h2>Modificadores</h2>
<p>La sintaxis Perl admite el uso de modificadores: letras que tienen un significado especial (que en general dependen del lenguaje que se esté usando) y que modifican el comportamiento del patrón.</p>
<p>Uno de los pocos modificadores que son comunes a todas las implementaciones de expresiones regulares compatibles con Perl es <strong>i</strong>, que indica que el patrón no debe considerar mayúsculas y minúsculas. Así, los siguientes patrones son equivalentes:<br />
<code>/[a-zA-Z]/</code><br />
<code>/[a-z]/i</code></p>
<p>La lista completa de modificadores soportados, como ya se mencionó, depende del lenguaje con el que se esté trabajando.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/111-diferencias-de-sintaxis-entre-posix-y-perl/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Tipos de coincidencias y referencias</title>
		<link>http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias</link>
		<comments>http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias#comments</comments>
		<pubDate>Sat, 27 Sep 2008 03:31:17 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=99</guid>
		<description><![CDATA[Ya habiendo terminado la descripción del lenguaje en el que se escriben las expresiones regulares, es hora de conocer algunas características relacionadas directamente con su uso en programas.
Las funciones de expresiones regulares
Las expresiones regulares tienen dos usos principales: validación de datos y búsqueda de información en cadenas cuya forma se conoce. También se pueden utilizar [...]]]></description>
			<content:encoded><![CDATA[<p>Ya habiendo terminado la descripción del lenguaje en el que se escriben las expresiones regulares, es hora de conocer algunas características relacionadas directamente con su uso en programas.</p>
<h2>Las funciones de expresiones regulares</h2>
<p>Las expresiones regulares tienen dos usos principales: validación de datos y búsqueda de información en cadenas cuya forma se conoce. También se pueden utilizar para separar una cadena en partes, pero esta es una característica poco usada.<br />
Los lenguajes de programación proveen normalmente diferentes funciones para las diferentes tareas:</p>
<ul>
<li>Funciones de coincidencia total: devuelven un valor verdadero si la cadena completa coincide con el patrón.</li>
<li>Funciones de coincidencia parcial: se encargan de recorrer la cadena buscando y almacenando las coincidencias del patrón con partes de la cadena.</li>
<li>Funciones de separación: dividen a la cadena en partes, usando una expresión regular como separador.</li>
<li>Funciones de reemplazo de texto: reemplazan las partes de la cadena original que coinciden con el patrón con una cadena predefinida.</li>
</ul>
<p>En próximas partes de esta serie se describirá el uso de expresiones regulares en varios lenguajes. Por ahora, vale mencionar que si se habla de PHP, las funciones que cumplen los puntos anteriores son <a href="http://php.net/ereg"><em>ereg</em></a> (puntos 1 y 2), <a href="http://php.net/split"><em>split</em></a> (punto 3) y <a href="http://php.net/ereg_replace"><em>ereg_replace</em></a> (punto 4).</p>
<h2>Tipos de coincidencia</h2>
<p>El tipo de coincidencia de un patrón con una cadena puede ser <em>total</em> o <em>parcial</em>. Es decir, si el patrón debe coincidir con la cadena completa (como en el caso de una validación, por ejemplo <a href="http://elcodiguero.com/php/50-validar-una-direccion-de-correo-electronico-con-php" title="Validar una dirección de correo electrónico con PHP">validación de direcciones de correo electrónico</a>) se dice que la coincidencia es total.</p>
<p>En otros casos se tienen cadenas de texto (a veces muy grandes) que tienen dos cualidades:</p>
<ol>
<li>La información que interesa es solamente una parte de la cadena completa</li>
<li>Su forma es conocida</li>
</ol>
<p>Es importante recalcar que la forma de la cadena es conocida: si no fuera así no podría escribirse un patrón que tomara solamente las partes que interesan.<br />
En estos casos en los que lo que importa es obtener datos de la cadena principal, incluso haciendo coincidir al patrón más de una vez en la cadena completa, se dice que la coincidencia es <strong>parcial</strong></p>
<p>Las coincidencias parciales serían muy poco útiles de no ser por una característica fundamental de los motores de expresiones regulares: las referencias.</p>
<h2>Referencias</h2>
<p>En las partes anteriores se describió la forma en la que trabajan los paréntesis, agrupando partes del patrón a las que se les debe aplicar un operador (|, *, +, {}).</p>
<p>Otra función de los paréntesis, la que se explicará en esta parte, es indicar qué partes del patrón interesa conservar, para así obtener información de la cadena analizada.<br />
Mejor expresado: La parte de la cadena que coincida con el patrón encerrado entre paréntesis será guardada y accesible luego de que el patrón se aplique sobre la cadena.</p>
<p>Dado que puede existir más de un juego de paréntesis, el motor de expresiones regulares otorga a cada juego un índice comenzando en 1 y hasta 9, contando desde la izquierda. El índice cero será la parte de la cadena que coincide con el patrón.</p>
<h4>Ejemplo</h4>
<p>Si el patrón es<br />
<code>&lt;a href="([^"]*)&#034;&gt;([^&lt;]*)&lt;/a&gt;</code><br />
y la cadena es un enlace normal<br />
<code>&lt;a href="http://alvlin.com"&gt;¡Visita mi sitio!&lt;/a&gt;</code><br />
La función que se utilice para comparar el patrón contra la cadena devolverá un vector de la siguiente forma:<br />
<code>vector[0] = &#039;&lt;a href=&#034;http://alvlin.com&#034;&gt;¡Visita mi sitio!&lt;/a&gt;&#039;
vector[1] = &#039;http://alvlin.com&#039;
vector[2] = &#039;¡Visita mi sitio!&#039;</code></p>
<p>Si no se desea que un juego de paréntesis &#034;capture&#034; la parte de la cadena que coincida con él, se debe agregar <strong>?:</strong> inmediatamente después del paréntesis de apertura. En el ejemplo, si no se desea que se capture el texto del enlace, puede escribirse el patrón de la siguiente forma:<br />
<code>&lt;a href="([^"]*)&#034;&gt;(?:[^&lt;]*)&lt;/a&gt;</code></p>
<p>Esto es útil para hacer al patrón un poco más eficiente (ya que capturar el trozo de cadena requiere algo de procesamiento extra) y además puede servir para patrones complejos que usen muchos juegos de paréntesis, dado que solamente se pueden capturar 9 &#034;trozos&#034;.</p>
<h3>Referencias &#034;normales&#034; (<em lang="en">referencing</em>)</h3>
<p>Se utilizan en las funciones de reemplazo de texto, normalmente como <strong>\\x</strong>, donde <strong>x</strong> es el índice del juego de paréntesis correspondiente.</p>
<h4>Ejemplo</h4>
<p>Un ejemplo muy común es la &#034;traducción&#034; de <a href="http://es.wikipedia.org/wiki/BBCode">etiquetas BBCode</a> en HTML. Para convertir<br />
<code>[b]Texto en Negrita[/b]</code><br />
en<br />
<code>&lt;strong&lt;Texto en Negrita&lt;/strong&gt;</code><br />
se puede utilizar la siguiente llamada a <a href="http://php.net/ereg_replace">ereg_replace</a> (en PHP):<br />
<code class="prettyprint">ereg_replace('[b](.*?)[/b]&#039;, &#039;&lt;strong&gt;\\1&lt;/strong&gt;&#039;, &#039;[b]Texto en Negrita[/b]&#039;);</code><br />
En este ejemplo, &#034;\\1&#034; hace referencia al primer juego de paréntesis. El motor de expresiones regulares lo sustituirá por la parte de la cadena que coincida con el patrón encerrado en ese primer juego de paréntesis.</p>
<h3>Referencias hacia atrás (<em lang="en">back referencing</em>)</h3>
<p>Otra forma de referencia es la referencia hacia atrás, también conocida como <em lang="en">back referencing</em>. En este caso no se utiliza para sustituir texto, sino por ejemplo para encontrar palabras duplicadas. El patrón:<br />
<code>(wiki)\\1</code><br />
Coincide con &#034;wikiwiki&#034;.</p>
<p>Esta forma de referencia no se utiliza demasiado, y no es soportada por los motores POSIX.<br />
De todas formas es interesante que exista.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/99-tipos-coincidencias-referencias/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Cuantificadores</title>
		<link>http://elcodiguero.com/programacion/95-cuantificadores</link>
		<comments>http://elcodiguero.com/programacion/95-cuantificadores#comments</comments>
		<pubDate>Fri, 19 Sep 2008 03:09:54 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=95</guid>
		<description><![CDATA[Introducción
He aquí el último tema de la serie básica sobre Expresiones Regulares: los cuantificadores.
Ciertos metacaracteres cumplen la función de indicar cuántas veces debe aparecer un patrón en una cadena para que la comparación sea exitosa. Estos caracteres se denominan cuantificadores, y son los siguientes:

* (asterisco)
Indica que el patrón debe aparecer cero o más veces
+ (más)
Indica [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción</h2>
<p>He aquí el último tema de la serie básica sobre Expresiones Regulares: los cuantificadores.<br />
Ciertos metacaracteres cumplen la función de indicar <em>cuántas veces</em> debe aparecer un patrón en una cadena para que la comparación sea exitosa. Estos caracteres se denominan <strong>cuantificadores</strong>, y son los siguientes:</p>
<dl>
<dt>* (asterisco)</dt>
<dd>Indica que el patrón debe aparecer cero o más veces</dd>
<dt>+ (más)</dt>
<dd>Indica que el patrón debe aparecer una o más veces</dd>
<dt>? (interrogación)</dt>
<dd>Indica que el patrón debe aparecer cero o una vez. Puede decirse que indica que el patrón es opcional (puede aparecer o no).</dd>
</dl>
<h2>¿Cómo se usan?</h2>
<p>Los cuantificadores deben ir a la derecha del trozo de patrón al que deben aplicarse. Por defecto se aplican a la clase de caracteres que los precede, pero su efecto puede extenderse usando los paréntesis.<br />
A continuación algunos ejemplos simples para dejar claro este punto:</p>
<p>[a-z]+ : &#034;una letra o más&#034;. Coincide con cualquier palabra.</p>
<p>1[a-z]? : &#034;Un 1 seguido o no por una letra&#034;. Coincide con &#034;1&#034;, &#034;1a&#034;, &#034;1b&#034; pero no con &#034;1ab&#034; (dado que ? indica que debe aparecer solamente 0 o 1 letra)</p>
<p>lab* : &#034;l, a, seguidas de 0 o más b&#034;. Coincide con &#034;la&#034;, &#034;lab&#034;, &#034;labbbbbbbbbbb&#034;, etc.</p>
<p>l(ab)*: &#034;l seguida de 0 o más secuencias ab&#034;. Coincide con &#034;l&#034;, &#034;lab&#034;, &#034;lababababab&#034;, etc.</p>
<h2>Las llaves</h2>
<p>Existe otro tipo de cuantificadores: las llaves (<strong>{</strong>, <strong>}</strong>). Se aplican de la misma manera que los otros cuantificadores (a continuación del patrón a <em>cuantificar</em>), y se utilizan para controlar la cantidad exacta de veces que el patrón debe aparecer.<br />
La sintaxis es<br />
<code>{min,max}</code></p>
<p>Que quiere decir que el patrón debe aparecer &#034;como mínimo <em>min</em> veces, y como máximo <em>max</em> veces&#034;. Tanto min como max son opcionales, cuando no aparece <em>min</em> se toma &#034;mínimo cero veces&#034; y cuando no aparece <em>max</em> se toma &#034;cualquier cantidad de veces&#034;. De esta forma, se pueden escribir los demás cuantificadores con la sintaxis de llaves:</p>
<table>
<thead>
<tr>
<th>Cuantificador</th>
<th>Equivale a</th>
</tr>
</thead>
<tbody>
<tr>
<td>?</td>
<td>{0,1}</td>
</tr>
<tr>
<td>*</td>
<td>{0,}</td>
</tr>
<tr>
<td>+</td>
<td>{1,}</td>
</tr>
</tbody>
</table>
<p>Las llaves también pueden usarse para indicar la cantidad exacta de veces que debe aparecer el patrón, para esto se omite la coma y se da un solo valor entre las llaves:<br />
<code>{num_veces}</code></p>
<h4>Ejemplo del uso de llaves</h4>
<p>Como ejemplo del uso de llaves, se usarán para un patrón similar al patrón dado como ejemplo en la tercera parte de esta serie: <a href="http://elcodiguero.com/programacion/74-exp-regulares-clases-de-caracteres" title="Exp. Regulares: Clases de caracteres">Exp. Regulares: Clases de caracteres</a><br />
<code>^[0-3][0-9][-/][0-1][0-9][-/][0-2][0-9][0-9][0-9]$</code></p>
<p>En este caso se considerará de la siguiente forma:<br />
<code>^[0-9][0-9][-/][0-9][0-9][-/][0-9][0-9][0-9][0-9]$</code><br />
Es decir, simplemente &#034;dos números seguidos de una barra o un guión, otros dos números separados por otra barra, y cuatro números al final&#034;. Para ejemplificar mejor el uso de las llaves, se permite que el año se exprese con solamente dos dígitos:<br />
<code>^[0-9]{2}[-/][0-9]{2}[-/][0-9]{2,4}$</code><br />
(este último patrón tiene el efecto desagradable de permitir que el año se represente con tres dígitos, pero como ejemplo funciona).</p>
<p>Si las explicaciones dadas hasta ahora fueron lo suficientemente claras, debería ser trivial la siguiente simplificación (o al menos entendible):<br />
<code>^([0-9]{2}[-/]){2}[0-9]{2,4}$</code><br />
Que utiliza los paréntesis para delimitar el efecto del segundo &#034;{2}&#034;.</p>
<h4>Un ejemplo más complejo</h4>
<p>A través de las partes de esta serie, se han explicado todos los elementos básicos que conforman la sintaxis de las expresiones regulares. Es hora de un ejemplo complejo que utilice varios de estos elementos.</p>
<p>Quizás sea más útil como ejercicio que como ejemplo: crear un patrón que coincida con &#039;1 de Mayo&#039;, &#039;1ero de Mayo&#039;, &#039;1 May&#039;, o incluso &#034;Primero de Mayo&#034;.</p>
<p>Los pasos a la hora de crear un patrón son siempre similares: es necesario localizar las partes comunes en las cadenas contra las que se va a comparar. Luego hay que trabajar con cada una de estas partes por separado.</p>
<p>En principio puede verse que las 4 cadenas comienzan con 1, 1ero o Primero. En la parte 4 (<a href="http://elcodiguero.com/programacion/85-parentesis-escape-caracteres-alternacion-patrones" title="Paréntesis, escape de caracteres, y alternación de patrones">Paréntesis, escape de caracteres, y alternación de patrones</a>) se explicó el uso del caracter de alternación, que es el que funciona en este caso:<br />
<code>1|1ero|Primero de Mayo</code><br />
Pero si se escribe de la forma anterior, el patrón coincidirá con &#034;1&#034;, con &#034;1ero&#034; y con &#034;Primero de Mayo&#034;. Se hace necesario limitar la acción de los |:<br />
<code>(1|1ero|Primero) de Mayo</code><br />
Con esto quedan cubiertas 3 de las 4 posibilidades.<br />
Siguiente problema: la palabra &#034;de&#034; no está en una de las cuatro cadenas, por lo que debe ser &#034;opcional&#034;. Se puede indicar que &#034;de&#034; es opcional usando el ? (ver más arriba):<br />
<code>(1|1ero|Primero)( de)? Mayo</code><br />
Aquí vale hacer dos observaciones. La primera es que se usan los paréntesis para indicar que la cadena completa &#034; de&#034; es opcional. Si se utilizara <em>de?</em>, lo opcional sería solamente la letra &#034;e&#034;.<br />
La segunda observación es que se debe recordar que el espacio es un caracter como cualquier otro, por lo que debe ser incluido en los patrones cuando se lo requiere. Por eso se utiliza &#034;( de)&#034; y no solamente &#034;(de)&#034;.<br />
Para finalizar, simplemente se necesita que el patrón coincida tanto con &#034;Mayo&#034; como con &#034;May&#034;, por lo que puede utilizarse de nuevo el caracter de alternación:<br />
<code>(1|1ero|Primero)( de)? (May|Mayo)</code><br />
Este patrón coincide con las cadenas propuestas, y también con otras que no tienen la forma correcta (por ejemplo, &#034;Primero May&#034;).<br />
Quizás sea una buena forma de ilustrar que las expresiones regulares solamente pueden validar forma, no contenido. Para validar contenido se deben utilizar más patrones (uno por cada contenido posible) o algo de lógica en el programa (recordar que las expresiones regulares se utilizan mayormente en el contexto de un programa, no por sí solas).</p>
<p>Otro punto interesante es que muchas veces hay varias formas de lograr el mismo efecto, con patrones diferentes. Todo depende de qué tanto se pueda &#034;factorizar&#034; la cadena buscada, qué tanta experiencia se tenga con las expresiones regulares, y qué tanta tolerancia ante los errores se tiene.<br />
Por ejemplo, en el patrón anterior pueden quitarse varias apariciones de | y sustituirse por ?:<br />
<code>(1(ero)?|Primero)( de)? Mayo?</code><br />
(recordando que, al no haber paréntesis para delimitar el efecto del último ?, éste se aplica solamente a la &#034;o&#034;.)</p>
<p>Este último patrón acepta los mismos errores que el anterior (por ejemplo, aceptará &#034;1 de May&#034;). Si este punto no es importante, podría reducirse aún más:<br />
<code>(1|Prim)(ero)?( de)? Mayo?</code><br />
Introduciendo un nuevo error, ahora &#034;Prim de Mayo&#034; también validará.</p>
<h2>El modificador ?</h2>
<p>Una característica a veces molesta de las expresiones regulares es que los cuantificadores tienen por defecto un comportamiento &#034;avaricioso&#034;: intentan coincidir con la mayor cadena posible.<br />
Este comportamiento por defecto conlleva problemas si no se tiene en cuenta.</p>
<h4>Ejemplo</h4>
<p>Se tiene la cadena<br />
<code>&lt;p&gt;Hola, soy &lt;strong&gt;un párrafo&lt;/strong&gt; en &lt;strong&gt;HTML&lt;/strong&gt;&lt;/p&gt;</code><br />
Y se desea obtener los trozos dentro de las etiquetas <em>strong</em>. En principio podría usarse el patrón<br />
<code>&lt;strong&gt;(.*)&lt;strong&gt;</code><br />
Pero por el comportamiento &#034;avaricioso&#034; por defecto, el subpatrón &#034;.*&#034; coincide con:<br />
<code>un párrafo&lt;/strong&gt; en &lt;strong&gt;HTML</code><br />
en vez de coincidir dos veces con el contenido de cada etiqueta <em>strong</em>.</p>
<p>El modificador <strong>?</strong> colocado inmediatamente después del cuantificador obliga a que éste se comporte de otra forma: ahora coincidirá con la menor cadena posible, no con la mayor.<br />
<code>&lt;strong&gt;(.*?)&lt;strong&gt;</code><br />
Produce como resultado los dos trozos de cadena por separado:<br />
<code>un párrafo
HTML</code></p>
<p>Aquí finaliza el tutorial &#034;teórico&#034; de Expresiones Regulares. Recomiendo tener cerca esta parte y las anteriores a la hora de leer las partes siguientes, que se centran en el uso de las Expresiones Regulares con varios lenguajes de programación.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/95-cuantificadores/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Paréntesis, escape de caracteres, y alternación de patrones</title>
		<link>http://elcodiguero.com/programacion/85-parentesis-escape-caracteres-alternacion-patrones</link>
		<comments>http://elcodiguero.com/programacion/85-parentesis-escape-caracteres-alternacion-patrones#comments</comments>
		<pubDate>Sat, 13 Sep 2008 02:08:46 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=85</guid>
		<description><![CDATA[En este capítulo se presenta el metacaracter de alternación, &#034;&#124;&#034;. Pero antes de describirlo se mencionan algunos caracteres que si bien no se consideran &#034;meta&#034;, tienen un significado especial: los paréntesis y la barra &#034;\&#034;, que sirve para escapar los caracteres con significado especial. 
Los paréntesis
Los paréntesis ( &#034;(&#034; y &#034;)&#034; ) tienen dos usos [...]]]></description>
			<content:encoded><![CDATA[<p>En este capítulo se presenta el metacaracter de alternación, &#034;|&#034;. Pero antes de describirlo se mencionan algunos caracteres que si bien no se consideran &#034;meta&#034;, tienen un significado especial: los paréntesis y la barra &#034;\&#034;, que sirve para escapar los caracteres con significado especial. </p>
<h2>Los paréntesis</h2>
<p>Los paréntesis ( &#034;(&#034; y &#034;)&#034; ) tienen dos usos principales: </p>
<ul>
<li>Delimitar el alcance de un cuantificador: Por defecto los cuantificadores toman la mayor cantidad de caracteres posible como el patrón a &#034;cuantificar&#034;, pero esto no es siempre lo que se necesita. Por ejemplo:<br />
<code>hola?</code><br />
no es lo mismo que<br />
<code>hol(a)?</code><br />
El caracter ? es un cuantificador que quiere decir &#034;uno o ninguno&#034; (se verá en el capítulo correspondiente). El primer patrón se lee como &#034;la secuencia &#039;hola&#039; o nada&#034;, mientras que el segundo se lee &#034;la secuencia &#039;hol&#039; seguida o no de una &#039;a&#039;&#034;.<br />
Visto de otro modo, el primer patrón coincide con la palabra &#034;hola&#034; y con una cadena vacía, mientras que el segundo coincide con &#034;hol&#034; y con &#034;hola&#034;</li>
<li>Referencia al contenido que coincide: El trozo de cadena que coincide con la parte del patrón encerrada entre paréntesis se guardará y se podrá usar más adelante. Por ejemplo:<br />
<code>(Hola)?, cómo estás</code><br />
No solamente coincide con la cadena &#034;Hola, cómo estás&#034; sino que además, al coincidir, la palabra &#034;Hola&#034; se guardará en una variable para su uso posterior.<br />
Esta funcionalidad es mejor explicada con ejemplos de código, que se incluirán en posteriores capítulos de esta serie. Lo importante es recordar que esta es una de las características más usadas, y que permite manipular cadenas de datos de forma sencilla.</li>
</ul>
<h2>Escape de caracteres</h2>
<p>Dado que hay caracteres que tienen un significado especial para el motor de expresiones regulares, el intentar buscar explícitamente alguno de ellos puede ser problemático.<br />
Tomando como ejemplo al punto, y suponiendo que se quiere encontrar &#034;alvlin.com&#034;, se podría intentar utilizar este patrón:<br />
<code>alvlin.com</code><br />
Que afortunadamente coincidiría con &#034;alvlin.com&#034;, pero lamentablemente también con &#034;alvlin#com&#034;, &#034;alvlinacom&#034;, &#034;alvlin!com&#034;, etc. El motivo es que, como se mencionó en partes anteriores, <em>el punto representa a cualquier caracter</em>.<br />
La solución a este problema, que se produce con cualquiera de los metacaracteres, es preceder con una barra &#034;\&#034; al caracter cuyo &#034;metacomportamiento&#034; el motor debe <em>olvidar</em>. Es decir, si se necesita que un punto en el patrón represente únicamente a un punto y no a otro caracter, el patrón de ejemplo debe escribirse como:<br />
<code>alvlin\.com</code></p>
<h2>El metacaracter de alternación: |</h2>
<p>El metacaracter | significa &#034;O&#034;, es decir &#034;un patrón o el otro&#034;.<br />
Se usa cuando se necesita buscar más de un tipo de secuencia de caracteres a la vez, o cuando se conoce que las cadenas a analizar contienen partes ligeramente diferentes, pero son iguales en otras.</p>
<p>En estos casos, se escriben al menos dos patrones que, unidos a través de la &#034;|&#034;, harán que la comparación sea exitosa si cualquiera de ellos coincide con la forma de la cadena.</p>
<h4>Ejemplo 1</h4>
<p>Por ejemplo, suponiendo un archivo como el siguiente (un diario personal, o un calendario):</p>
<pre>Lunes: asdlñfkhadflh1o2333fdafdf
Martes: añsdlkfher8y43r10uerfrfdmslsdfgbf
Miércoles: tggggggfodfuhvbnvcleortgb
[continúa]
Lunes: 102354ty8ghfjdoiskcivjnvmc
[continúa]</pre>
<p>Y suponiendo que se quiere analizar su contenido para obtener solamente aquellas líneas que comienzan con &#034;Lunes:&#034; o &#034;Martes&#034;, se puede usar un patrón como el siguiente:<br />
<code>Lunes:|Martes:</code></p>
<p>Por defecto la alternación se aplica como &#034;todo lo que esté antes de | O todo lo que esté después&#034;.<br />
Esto hace que el &#034;:&#034; al final de cada día no pueda llevarse al final<br />
<code>Lunes|Martes:</code><br />
Ya que este patrón coincide con &#034;Lunes&#034; o con &#034;Martes:&#034;.</p>
<p>Para delimitar el campo de acción del operador, se pueden usar los paréntesis:<br />
<code>(Lunes|Martes):</code><br />
Este patrón coincide se lee como: &#034;Lunes&#034; o &#034;Martes&#034;, cualquiera de los dos seguido por un &#034;:&#034;.</p>
<h4>Ejemplo 2</h4>
<p>Una falta de ortografía muy común es <em>targeta</em> (una <em>g</em> donde debería ir una j). Si la idea es encontrar cualquiera de las dos &#034;versiones&#034; de la palabra, hay varios caminos posibles:</p>
<ul>
<li>Clase de caracteres: <code>tar[gj]eta</code></li>
<li>Alternación (con paréntesis para dejar claro el campo de acción de |): <code>tar(j|g)eta</code></li>
<li>Alternación: <code>tarjeta|targeta</code></li>
</ul>
<p>Esta última forma demuestra una ventaja de la alternación sobre las clases de caracteres: con | se pueden usar como &#039;opciones&#039; cadenas y patrones tan complejos como se necesite, mientras que en una clase solamente se pueden listar caracteres individuales (o alguna de las clases predefinidas, que en realidad no son otra cosa que listados de caracteres).</p>
<p>Vale la pena observar que <code>tar[g|j]eta</code> no sirve, ya que dentro de una clase de caracteres &#039;|&#039; pierde su significado especial.<br />
Tampoco funciona <code>targ|jeta</code> porque el significado de ese patrón es &#034;targ O jeta&#034;</p>
<h3>Jugando con las anclas</h3>
<p>Usadas con descuido, las anclas (^ y $) dentro de cada alternativa pueden llevar a resultados inesperados. Volviendo al Ejemplo 1, si se lee con atención se notará que la intención es coincidir con &#034;Lunes&#034; o &#034;Martes&#034; <strong>al comienzo</strong> de cada línea.<br />
Los patrones propuestos hasta ahora no usan ningún ancla, por lo que no cumplen que la palabra deba estar al principio.<br />
Si se hace sin cuidado, podría escribirse este patrón:<br />
<code>^Lunes:|Martes:</code><br />
Que, en vez de coincidir con &#034;la palabra &#039;Lunes&#039; o la palabra &#039;Martes&#039; al principio de la cadena&#034; coincide con &#034;La palabra &#039;Lunes&#039; al principio de la cadena, o la palabra &#039;Martes&#039; en cualquier lugar de la misma&#034;. Esto sucede porque no se han usado paréntesis para delimitar el efecto de |. El patrón funciona correctamente si se agregan los paréntesis adecuados:<br />
<code>^(Lunes|Martes):</code></p>
<p>Que es equivalente a utilizar combinados los siguientes 2 patrones:<br />
<code>^Lunes:
^Martes:</code></p>
<p>Cabe mencionar que<br />
<code>^(Lunes|Martes):</code></p>
<p>es equivalente al más largo pero quizás más entendible<br />
<code>^Lunes:|^Martes:</code></p>
<p>Las alternativas no pueden &#034;negarse&#034; como se hace con las clases de caracteres: no se puede hacer &#034;que esté X o que NO esté Y&#034;. Sin embargo, como cada alternativa es un patrón completo, siempre pueden hacerse las negaciones necesarias en el patrón (en la alternativa) mismo.</p>
<p>Como último comentario, mencionar que el número de alternativas que se pueden utilizar no está limitado, en los ejemplos siempre se utilizaron dos pero pueden utilizarse tantas alternativas como sean necesarias. El patrón<br />
<code>^(Lunes|Martes|Miércoles|Jueves|Viernes|Sábado|Domingo):</code><br />
es perfectamente válido.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/85-parentesis-escape-caracteres-alternacion-patrones/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Clases de caracteres predefinidas</title>
		<link>http://elcodiguero.com/programacion/81-clases-caracteres-predefinidas</link>
		<comments>http://elcodiguero.com/programacion/81-clases-caracteres-predefinidas#comments</comments>
		<pubDate>Thu, 04 Sep 2008 02:32:41 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=81</guid>
		<description><![CDATA[Esta parte termina el tema de las clases de caracteres.
El punto
El punto (.) es un metacaracter comodín, representa a cualquier caracter, incluso a aquellos caracteres no visibles (saltos de línea, por ejemplo).
Pero no se usa dentro de clases de caracteres, de hecho, dentro de una clase se considera un caracter normal. Es lógico que así [...]]]></description>
			<content:encoded><![CDATA[<p>Esta parte termina el tema de las clases de caracteres.</p>
<h2>El punto</h2>
<p>El punto (<strong>.</strong>) es un metacaracter comodín, representa a cualquier caracter, incluso a aquellos caracteres no visibles (saltos de línea, por ejemplo).<br />
Pero no se usa dentro de clases de caracteres, de hecho, dentro de una clase se considera un caracter normal. Es lógico que así sea, dado que de otra forma la clase de caracteres perdería sentido.</p>
<p>Si dentro de la clase se considerara como metacaracter, una clase como <code>[asd.]</code> se leería como &#034;a, s, d o cualquier caracter&#034;), sería lo mismo que <code>[.]</code> (&#034;cualquier caracter&#034;).<br />
Peor aún, una clase como <code>[^.]</code> coincidiría con &#039;un caracter que NO es ningún caracter&#039;, que es obviamente una contradicción.</p>
<p>Por este motivo el punto solo tiene su <em>metasignificado</em> <strong>fuera de las clases</strong>.</p>
<p>Por ejemplo, el patrón<br />
<code>^da.$</code><br />
(literalmente: una cadena que comienza con &#039;d&#039;, luego tiene una &#039;a&#039;, y termina con un caracter cualquiera), coincide con <em>das</em>, <em>dar</em>, <em>dat</em>, <em>daf</em>, <em>da_</em>, <em>da.</em>, <em>da=</em>, etc.</p>
<p>Si la intención es coincidir únicamente con &#039;da.&#039; (d a punto), tendría que usar el patrón: &#039;da[.]&#039; o &#039;da\.&#039;, en el segundo caso se escapa el punto para que se tome literalmente.</p>
<p>La inclusión del punto dentro del tema de <em>Clases de caracteres</em> obedece al hecho de que, al igual que las clases, es una forma de representar posibles caracteres que deben aparecer en una posición determinada.</p>
<h2>Clases predefinidas</h2>
<p>Dado el uso frecuente de ciertos conjuntos de caracteres, los motores de expresiones regulares incluyen algunos rangos predefinidos, que por practicidad se han listados en la siguiente tabla.</p>
<table>
<thead>
<tr>
<td>POSIX</td>
<td>Perl</td>
<td>Clase equivalente</td>
<td>Representa a</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>[:alnum:]</code></td>
<td></td>
<td><code>[A-Za-z0-9]</code></td>
<td>Números y letras</td>
</tr>
<tr>
<td><code>[:word:]</code></td>
<td><code>\w</code></td>
<td><code>[A-Za-z0-9_]</code></td>
<td>Números, letras, y el infraguión &#034;_&#034;</td>
</tr>
<tr>
<td></td>
<td><code>\W</code></td>
<td><code>[^\w]</code></td>
<td>Negación de la anterior</td>
</tr>
<tr>
<td><code>[:alpha:]</code></td>
<td></td>
<td><code>[A-Za-z]</code></td>
<td>Letras</td>
</tr>
<tr>
<td><code>[:blank:]</code></td>
<td></td>
<td><code>[ \t]</code></td>
<td>Espacio y tabulador</td>
</tr>
<tr>
<td><code>[:cntrl:]</code></td>
<td></td>
<td><code>[\x00-\x1F\x7F]</code></td>
<td>Caracteres de control (los primeros de la tabla ASCII)</td>
</tr>
<tr>
<td><code>[:digit:]</code></td>
<td><code>\d</code></td>
<td><code>[0-9]</code></td>
<td>Números</td>
</tr>
<tr>
<td></td>
<td><code>\D</code></td>
<td><code>[^\d]</code></td>
<td>Negación de la anterior</td>
</tr>
<tr>
<td><code>[:graph:]</code></td>
<td></td>
<td><code>[\x21-\x7E]</code></td>
<td>Caracteres visibles (en oposición a los caracteres de control)</td>
</tr>
<tr>
<td><code>[:lower:]</code></td>
<td></td>
<td><code>[a-z]</code></td>
<td>Letras minúsculas</td>
</tr>
<tr>
<td><code>[:print:]</code></td>
<td></td>
<td><code>[\x20-\x7E]</code></td>
<td>Caracteres visibles y espacios</td>
</tr>
<tr>
<td><code>[:punct:]</code></td>
<td></td>
<td><code>[-!"#$%&amp;'()*+,./:;&lt;=&gt;?@[\\\]_`{|}~]</code></td>
<td>Caracteres de puntuación</td>
</tr>
<tr>
<td><code>[:space:]</code></td>
<td><code>\s</code></td>
<td><code>[ \t\r\n\v\f]</code></td>
<td>Caracteres de espaciado (espacio, tabulador, salto de línea)</td>
</tr>
<tr>
<td></td>
<td><code>\S</code></td>
<td><code>[^\s]</code></td>
<td>Negación de la anterior</td>
</tr>
<tr>
<td><code>[:upper:]</code></td>
<td></td>
<td><code>[A-Z]</code></td>
<td>Letras mayúsculas</td>
</tr>
<tr>
<td><code>[:xdigit:]</code></td>
<td></td>
<td><code>[A-Fa-f0-9]</code></td>
<td>Dígitos hexadecimales</td>
</tr>
</tbody>
</table>
<p>Las indicadas como &#034;POSIX&#034; solamente pueden utilizarse dentro de una clase delimitada por corchetes, mientras que las de Perl pueden usarse en cualquier parte del patrón.<br />
Ejemplos de su uso pueden ser:<br />
<code>[[:digit:]ab] : coincide con un número, una letra a, o una b</code><br />
<code>\d\d\d : 3 números</code></p>
<p>Lo que la tabla indica es &#034;dónde se define&#034;, no &#034;dónde se soporta&#034;. Esto es, se puede usar las clases POSIX en Perl y las de Perl en motores compatibles con POSIX. No se está indicando tampoco que todos los motores deban entender todas las clases, algunos pueden omitir algunas o, por otro lado, agregar otras.</p>
<p>Este capítulo finaliza el tema de las clases de caracteres, el siguiente entrará en el tema de los cuantificadores y el caracter de alternación.</p>
<p>Como &#034;ejercicio&#034;, vale la pena ver cómo cambia la expresión regular creada al final del capítulo anterior si se hace uso del punto o de las clases predefinidas:<br />
<code>^[0-3][0-9][-/][0-1][0-9][-/][0-2][0-9][0-9][0-9]$</code></p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/81-clases-caracteres-predefinidas/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Exp. Regulares: Clases de caracteres</title>
		<link>http://elcodiguero.com/programacion/74-exp-regulares-clases-de-caracteres</link>
		<comments>http://elcodiguero.com/programacion/74-exp-regulares-clases-de-caracteres#comments</comments>
		<pubDate>Mon, 25 Aug 2008 03:22:45 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=74</guid>
		<description><![CDATA[Las clases de caracteres son conjuntos de caracteres que representan &#039;opciones&#039; para el mismo caracter dentro del patrón. Una clase de caracteres se delimita con [ y ]
Las clases de caracteres se utilizan en aquellos casos en los que se sabe que en la cadena deben aparecer un conjunto limitado de caracteres en una cierta [...]]]></description>
			<content:encoded><![CDATA[<p>Las <dfn>clases de caracteres</dfn> son conjuntos de caracteres que representan &#039;opciones&#039; para el mismo caracter dentro del patrón. Una clase de caracteres se delimita con <strong>[</strong> y <strong>]</strong></p>
<p>Las clases de caracteres se utilizan en aquellos casos en los que se sabe que en la cadena deben aparecer un conjunto limitado de caracteres en una cierta posición.</p>
<p><strong>Ejemplo:</strong> [sz]<br />
Esta clase de caracteres coincidirá si, en el lugar del patrón en la que se ubica, hay una &#034;s&#034; o una &#034;z&#034;.</p>
<p>patron: ca[sz]a<br />
Se lee como: &#034;una c, seguida de una a, seguida de una s o una z, seguida de una a&#034;.<br />
Las cadenas &#034;casa&#034;, &#034;caza&#034; y &#034;me voy de casa&#034; coinciden con el patrón.<br />
Las cadenas &#034;cata&#034; y &#034;cat&#034; no coinciden.</p>
<p><strong>Comentario importante</strong>: antes de intentar escribir un patrón, es necesario tener clara la estructura de la cadena que se va a a analizar. Si no se puede encontrar una estructura, no será posible escribir un patrón que funcione en todos los casos.</p>
<h4>Notas</h4>
<ul>
<li>El orden de los caracteres dentro de la clase es irrelevante: [sz] funciona igual que [zs]</li>
<li>La clase no está limitada en la cantidad de caracteres que puede contener</li>
<li>La clase solamente representa a un caracter presente: el patrón &#034;Hol[abc]&#034; coincide con &#034;Hola&#034;, &#034;Holb&#034;, &#034;Holc&#034;, pero NO con &#034;Hol&#034;.</li>
<li>La clase solamente se compara con 1 caracter. Si se tiene el patrón<br />
<code>Hol[abc]$</code><br />
Que quiere decir &#034;que el final de la cadena sea una letra H, seguida de o, seguida de l, luego una letra a o b o c&#034;, la cadena &#034;Hola&#034; coincidirá (así como &#034;Holb&#034; y &#034;Holc&#034;) pero &#034;Holaa&#034; no.</li>
</ul>
<h2>Rangos</h2>
<p>Un <dfn>rango</dfn> es una clase de caracteres particular, en la que se incluye una lista abreviada.</p>
<p>Por ejemplo, si se necesita que el patrón coincida con un número cualquiera, se puede usar:</p>
<ul>
<li>La opción completa, con cualquiera de sus variantes (recuérdese que el orden dentro de la clase no es importante): [0123456789] o la equivalente [3452167809]</li>
<li>Un rango, que define el primer caracter, el caracter final, y el metacaracter &#034;-&#034; (guión simple) entre ellos:<br />
<code>[0-9]</code>
</li>
</ul>
<h3>Características</h3>
<p>Un rango no tiene por qué ser completo (en el caso de los números, no es necesario que sea 0-9): <code>[2-4] es equivalente a [234].</code></p>
<p>Tampoco está limitado a números, funciona con letras también:<br />
<code>[a-z] = [abcdefghijklmnopqrstuvwxyz]</code><br />
<code>[e-m] = [efghijklm]</code></p>
<p>La clase de caracteres puede contener rangos y caracteres individuales, o varios rangos:<br />
<code>[0-9·"] es equivalente a [0123456789·"]</code><br />
<code>[a0-9z] equivale a [a0123456789z]</code><br />
<code>[0-9a-z]
[0-9a-z"·$]</code></p>
<p><strong>Nota</strong>: en la mayoría de los motores de expresiones regulares, [a-z] no coincide con caracteres acentuados o con diéresis, ni con la letra ñ. Esto hace necesario que deban definirse específicamente, por ejemplo:</p>
<p><code>[0-9a-záéíóú]</code></p>
<p>Hacia el final del tutorial se hará un comentario más extenso sobre este punto.</p>
<h2>Metacaracteres</h2>
<p>Las clases tienen sus propios metacaracteres, que no necesariamente tienen el mismo significado dentro y fuera de la clase.</p>
<h3>El guión</h3>
<p>Como ya se comentó, si se coloca entre dos caracteres cualesquiera, provocará que el motor intente generar un rango entre ambos. Esto no es siempre lo que se busca, si por accidente la clase de caracteres termina siendo<br />
<code>[4-a]</code><br />
con la intención de que coincida con &#034;un 4, un guión o una a&#034;, el patrón no será válido (no se puede generar un rango entre el 4 y la a).</p>
<p>Por lo que, si se desea encontrar un guión en el texto, se lo debe colocar al comienzo o al final de la clase de caracteres (justo después de <strong>[</strong> o justo antes de <strong>]</strong>). En ese caso, al no estar entre 2 caracteres de la clase, no adquiere su &#039;metacomportamiento&#039;.</p>
<h3>El acento circunflejo</h3>
<p>Dentro de la clase de caracteres el acento circunflejo (<strong>^</strong>) pierde su comportamiento de ancla, y se transforma en un operador de negación.<br />
Esto es útil cuando no se busca que cierto caracter esté en la cadena, sino que se busca que NO esté.</p>
<p><strong>Ejemplo</strong>: Si se quiere validar que una cadena contenga cualquier caracter que no sea un número, se puede usar<br />
<code>[^0123456789]</code><br />
O, en notación de rango:<br />
<code>[^0-9]</code></p>
<p>Es importante destacar que, para que el ^ adquiera su metacomportamiento, debe ir ubicado inmediatamente después de [. En el patrón<br />
<code>[0-9^a-z]</code><br />
no se indica &#034;<em>un número o un caracter que no sea una letra</em>&#034; sino &#034;<em>un número, una letra o un ^</em>&#034;</p>
<p>Un ejemplo más:<br />
Los metacaracteres pueden combinarse, el patrón<br />
<code>^[^0-9]</code><br />
representa a una cadena que comienza (<strong>^</strong>) con algo que NO (<strong>[^</strong>) es un número (<strong>0-9</strong>).</p>
<p class="notas"><strong>Nota</strong>: Anteriormente se mencionó que para ser tomado literalmente, el guión (-) debe ir a continuación de [ o antes de ]. Hay una tercera opción: un guión ubicado a continuación de ^ también será tomado literalmente.</p>
<h2>Resumen para las clases de caracteres</h2>
<p>Las clases de caracteres se utilizan cuando se tienen opciones sobre caracteres en ciertas partes de la cadena, por ejemplo si se sabe que la cadena comienza (o DEBE comenzar para ser aceptada como válida) con un número, pero puede ser cualquier número, se puede utilizar el siguiente patrón:<br />
<code>^[0-9]</code></p>
<p>Una clase únicamente representa a 1 caracter de la cadena, y únicamente a un caracter presente, es decir, debe haber un caracter para poder coincidir:<br />
<code>Hol[^a]</code><br />
Coincide con &#039;Holo&#039;, &#039;Hole&#039;, pero NO con &#039;Hol&#039;.</p>
<p>Las clases tienen sus propios metacaracteres, ocurriendo a veces que el mismo caracter tiene un significado fuera de la clase, al comienzo de la misma, o incluso dentro de la clase pero no al comienzo, siendo el acento circunflejo <strong>^</strong> ejemplo de esto.</p>
<p>Los metacaracteres para las clases son:</p>
<ul>
<li>- (guión): si está en los extremos de la clase, solo representa a un guión, pero si no está en los extremos sirve para formar un rango entre los caracteres adyacentes: en <strong>[-a]</strong> solo representa a un guión, mientras que en <strong>[0-9]</strong> forma el rango que representa a los números entre 0 y 9 (Nota: el rango [1-3] representa números entre 1 y 3, no es obligatorio representar a un rango completo)</li>
<li>^ (circunflejo): únicamente es metacaracter si está al comienzo de la clase. Representa la negación, es decir, que para que se produzca una coincidencia los caracteres que forman la clase NO deben estar presentes.</li>
<li>[, ] : son metacaracteres por el hecho de limitar la clase, si se requiere incluir alguno de los dos en la clase se debe escapar colocándole una barra &#039;\&#039; delante, para que se lo tome literalmente.</li>
</ul>
<h2>Comentario sobre lo comentado</h2>
<p>Solamente se han mencionado unos pocos puntos sobre las expresiones regulares, sin embargo eso basta para construir muchos patrones relativamente complejos.</p>
<p><strong>Ejemplo</strong>: Se supone que una fecha debe estar formada por dos números representando el día, dos números representando el mes y cuatro números representando el año, cada parte separada por una barra (&#034;/&#034;) o un guión (&#034;-&#034;).<br />
Se puede construir entonces el siguiente patrón, que cumple estas reglas<br />
<code>^[0-3][0-9][-/][0-1][0-9][-/][0-2][0-9][0-9][0-9]$</code></p>
<p>Que literalmente significa:<br />
^	La cadena comienza<br />
[0-3]	Con un número entre cero y tres (ya que no hay días 40)<br />
[0-9]	Sigue con otro número<br />
[-/]	Luego hay un guión o una barra (nótese que el guión al comienzo de la clase no tiene su significado especial)<br />
[0-1]	Lo sigue un número entre cero y uno (ya que no hay mes 20)<br />
[0-9]	Luego otro número<br />
[-/]	Otro guión o barra<br />
[0-2]	Luego un número entre cero y dos (ya que no hay año 3000, al menos en el calendario cristiano)<br />
[0-9][0-9][0-9]	y luego tres números más<br />
$	al final de la cadena.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/74-exp-regulares-clases-de-caracteres/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Metacaracteres: Anclas</title>
		<link>http://elcodiguero.com/programacion/59-metacaracteres-anclas</link>
		<comments>http://elcodiguero.com/programacion/59-metacaracteres-anclas#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:52:17 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=59</guid>
		<description><![CDATA[Existen dos caracteres que actúan como anclas: fijan la posición de la cadena en la que debe encontrarse el patrón buscado. Estos caracteres son 

^ (acento circunflejo) Indica que el patrón debe estar al comienzo de la cadena
$ (signo de moneda) Indica que el patrón debe estar al final de la cadena.

Ejemplo: en la frase [...]]]></description>
			<content:encoded><![CDATA[<p>Existen dos caracteres que actúan como anclas: fijan la posición de la cadena en la que debe encontrarse el patrón buscado. Estos caracteres son </p>
<ol>
<li><strong>^</strong> (acento circunflejo) Indica que el patrón debe estar al comienzo de la cadena</li>
<li><strong>$</strong> (signo de moneda) Indica que el patrón debe estar al final de la cadena.</li>
</ol>
<p>Ejemplo: en la frase &#034;Hola, ¿cómo estás?&#034;, &#034;Hola&#034; está al principio, por lo que se puede usar:<br />
<code>^Hola</code></p>
<p>Y &#034;estás?&#034; se encuentra al final, por lo que se puede usar también:<br />
<code>estás?$</code></p>
<p>Las anclas pueden combinarse en el mismo patrón, por lo que si se busca la cadena exacta “Hola, ¿cómo estás?”, se puede usar:<br />
<code><strong>^</strong>Hola, ¿cómo estás?<strong>$</strong></code></p>
<p class="nota"><strong>Nota</strong>: Todos los metacaracteres pueden combinarse en el mismo patrón, y durante este tutorial se intentará hacer énfasis en este punto.</p>
<p>A continuación algunos ejemplos:</p>
<p><strong>Ejemplo 1</strong><br />
Cadena original: &#034;Hola, ¿cómo estás?&#034; (sin las comillas)</p>
<table>
<thead>
<tr>
<td>Patrón</td>
<td>¿Coincide?</td>
<td>¿Por qué?</td>
</tr>
</thead>
<tbody>
<tr>
<td>^Hola</td>
<td>si</td>
<td>&#034;Hola&#034; esta al principio de la cadena</td>
</tr>
<tr>
<td>estás?$</td>
<td>si</td>
<td>&#034;estás?&#034; está al final de la cadena</td>
</tr>
<tr>
<td>^estás</td>
<td>no</td>
<td>&#034;estás&#034; se encuentra dentro de la cadena, pero no al principio.</td>
</tr>
</tbody>
</table>
<h4>Ejemplo 2</h4>
<p>Cadena original: &#034;Buenos días, ¿cómo estás?” (sin las comillas)</p>
<table>
<thead>
<tr>
<td>Patrón</td>
<td>¿Coincide?</td>
<td>¿Por qué?</td>
</tr>
</thead>
<tbody>
<tr>
<td>^Hola</td>
<td>no</td>
<td>&#034;Hola&#034; no está al principio</td>
</tr>
<tr>
<td>estás?$</td>
<td>si</td>
<td>&#034;estás?&#034; está al final de la cadena</td>
</tr>
</tbody>
</table>
<h4>Ejemplo 3</h4>
<p>Cadena original: &#034;Hola, amigo&#034;.</p>
<table>
<thead>
<tr>
<td>Patrón</td>
<td>¿Coincide?</td>
<td>¿Por qué?</td>
</tr>
</thead>
<tbody>
<tr>
<td>^Hola</td>
<td>si</td>
<td>&#034;Hola&#034; está al principio</td>
</tr>
<tr>
<td>^Hola$</td>
<td>no</td>
<td>la cadena no es &#034;Hola&#034;, aunque lo contenga</td>
</tr>
<tr>
<td>amigo$</td>
<td>si</td>
<td>&#034;amigo&#034; está al final</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/59-metacaracteres-anclas/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Expresiones regulares: Introducción</title>
		<link>http://elcodiguero.com/programacion/56-expresiones-regulares-introduccion</link>
		<comments>http://elcodiguero.com/programacion/56-expresiones-regulares-introduccion#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:24:20 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=56</guid>
		<description><![CDATA[Una definición posible de lo que son las "expresiones regulares" (también llamadas "patrones") es la siguiente: "Una expresión regular es una secuencia de caracteres que describe la forma de otra en un lenguaje formal". Son la mejor forma de analizar texto, y aunque tienen sus "trucos", no son tan complicadas como parecen una vez que uno se familiariza con ellas.]]></description>
			<content:encoded><![CDATA[<p>Hace mucho tiempo que tengo este tutorial pendiente, lo había escrito antes pero por diversos motivos ya no estaba disponible. Aproveché para reescribirlo y expandirlo, pronto habrá incluso una versión PDF completa descargable.<br />
Me gustaría que en caso de encontrar algún error (técnico, sintáctico, semántico, ortográfico o gramatical) me lo hicieran saber usando los comentarios de cada entrada.</p>
<h2>Definición y conceptos</h2>
<p>Una definición posible de lo que son las &#034;expresiones regulares&#034; (también llamadas &#034;patrones&#034;) es la siguiente:</p>
<p><em>&#034;Una <dfn>expresión regular</dfn> es una secuencia de caracteres que describe la forma de otra en un lenguaje formal&#034;</em>.</p>
<p>De un modo más práctico: se escribe una secuencia de caracteres que un programa (llamado <em>motor</em>) entiende, y que se comparará contra un texto dado. El objetivo de esto suele ser validar datos de entrada en una aplicación (es decir, comprobar que los datos tienen la forma necesaria) o buscar trozos de texto en cadenas mayores.</p>
<p>Aunque en principio el concepto pueda sonar extraño, en realidad cualquier persona está acostumbrada al uso de &#034;patrones&#034;, véase como ejemplo la siguiente descripción:</p>
<p>&#034;Un nombre de usuario seguido de una arroba (@) y de un nombre de dominio&#034;</p>
<p>Si al leer eso se imagina una dirección de correo electrónico, queda probado que nuestra mente está habituada al uso de <em>patrones</em>, aunque sean simples.</p>
<p>Pueden encontrarse muchos otros ejemplos cotidianos en los que cualquier persona es capaz de reconocer &#034;algo&#034; mediante una descripción de &#034;su forma básica&#034; (uno bien claro: una <em>mesa</em> es una <em>superficie plana</em> sostenida por <em>patas</em>).</p>
<p>La diferencia principal entre estos ejemplos y las expresiones regulares es que las computadoras no son capaces de entender conceptos como &#034;nombre de usuario&#034; o &#034;nombre de dominio&#034;: solamente reconocen caracteres. Esto hace necesario un análisis previo del texto buscado (partes repetidas, secuencias diferentes pero siempre del mismo largo, espacios entre partes, etc) para poder escribir un patrón efectivo.</p>
<h3>Conceptos</h3>
<p>Ahora, algunos términos relacionados con el tema.</p>
<h4>Motor de expresiones regulares</h4>
<p>El <dfn>motor de expresiones regulares</dfn> es el programa encargado de procesar el patrón y realizar la comparación con el texto. Los dos tipos de motores más usados (según la sintaxis de patrones que aceptan) son los compatibles con <a href="http://www.perl.org/">Perl</a> y los compatibles con <a href="http://es.wikipedia.org/wiki/POSIX"><acronym title="Portable Operating System Interface">POSIX</acronym></a> (y POSIX extendido). Casi todo lo que se explica en este texto usa la sintaxis POSIX (aunque es compatible con ambas sintaxis). En los capítulos finales se encuentran comentarios que ayudarán a escribir patrones con ambas sintaxis casi sin diferencias.</p>
<h4>Metacaracteres</h4>
<p>Los <dfn>metacaracteres</dfn> son caracteres que tienen un significado particular además de su significado literal. Algunos incluso tienen varios significados &#034;extra&#034;, dependientes del contexto en el que se encuentran. Se describirán más adelante, pero es importante conservar el concepto al leer los capítulos siguientes.</p>
<h4>Patrón</h4>
<p>El patrón o &#034;expresión regular&#034; es un conjunto de caracteres. No hay límite de complejidad o largo, y un patrón simple bien puede ser simplemente &#034;a&#034;. Para este patrón, el motor de expresiones regulares devolverá una comparación exitosa con cualquier texto que contenga una letra &#034;a&#034;.</p>
<h2>Uso de las expresiones regulares</h2>
<p>Todos los lenguajes de programación proveen alguna forma de trabajar con patrones. Por simplicidad este tutorial intenta ser independiente del lenguaje, mostrando tablas de resultados en vez de ejemplos de código. En los capítulos finales se describirá el uso con <a href="http://www.php.net">PHP</a>, <a href="http://java.sun.com">Java</a>, <a href="http://www.perl.org/">Perl</a>, <a href="http://www.python.org">Python</a> y <a href="http://es.wikipedia.org/wiki/Javascript">Javascript</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/programacion/56-expresiones-regulares-introduccion/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Bots: servicios de internet y desconocidos</title>
		<link>http://elcodiguero.com/general/55-bots-servicios-de-internet-y-desconocidos</link>
		<comments>http://elcodiguero.com/general/55-bots-servicios-de-internet-y-desconocidos#comments</comments>
		<pubDate>Thu, 03 Jul 2008 20:38:13 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=55</guid>
		<description><![CDATA[Servicios de internet
En esta categoría he incluido a los robots que proveen servicios que no entran en otras categorías, por ejemplo el robot del Internet Archive o el Validador del W3C

ia_archiver
Se identifica como: ia_archiver-web.archive.org
Éste es el robot del Internet Archive. Este sitio mantiene copias de los sitios para &#034;futura referencia&#034;, y a veces resulta bastante [...]]]></description>
			<content:encoded><![CDATA[<h3>Servicios de internet</h3>
<p>En esta categoría he incluido a los robots que proveen servicios que no entran en otras categorías, por ejemplo el robot del <a href="http://archive.org">Internet Archive</a> o el <a href="http://validator.w3.org">Validador del W3C</a></p>
<dl>
<dt><a href="http://archive.org">ia_archiver</a></dt>
<dd>Se identifica como: <strong>ia_archiver-web.archive.org</strong><br />
Éste es el robot del <em>Internet Archive</em>. Este sitio mantiene copias de los sitios para &#034;futura referencia&#034;, y a veces resulta bastante entretenido ver cómo se veía un sitio cualquiera hace algunos años.</dd>
<dt><a href="http://www.netcraft.com">Netcraft Web Server Survey</a></dt>
<dd>Se identifica como: <strong>Mozilla/4.0 (compatible; Netcraft Web Server Survey)</strong><br />
Este robot pertenece a <em>Netcraft</em>, y de vez en cuando rastrea Internet para conocer el servidor que aloja al sitio. Con esta información, recabada de millones de sitios, Netcraft elabora las estadísticas más completas sobre el uso de los diferentes servidores del mercado (Apache, IIS, etc).</dd>
<dt><a href="http://www.domaintools.com/webmasters/surveybot.html">SurveyBot - Whois Source</a></dt>
<dd>Se identifica como: <strong>SurveyBot/2.3 (Whois Source)</strong><br />
Simplemente hace peticiones a los sitios con el objetivo de recopilar estadísticas sobre los mismos, no recorre ni almacena páginas.<br />
Pertenece a DomainTools, una empresa de registro de dominios que nutre su motor de búsqueda con la información recopilada por el robot.</dd>
<dt><a href="http://validator.w3.org">W3C_Validator</a></dt>
<dd>Se identifica como: <strong>W3C_Validator/1.575</strong><br />
Así se identifica el <a href="http://validator.w3.org">validador del w3c</a> cuando tiene que revisar una página web.</dd>
</dl>
<h3>Desconocidos</h3>
<p>Algunos agentes de usuario me son desconocidos. No pude encontrar información sobre ellos, a pesar de lo obvios que parecen los nombres de algunos de ellos. No quiere decir que sean &#034;malos&#034;, pero el hecho de que algunos intenten disfrazarse como otros robots da para desconfiar.</p>
<dl>
<dt>MSIE6.0</dt>
<dd>Este robot pretende ser Internet Explorer. Sin embargo, la cadena que usa para identificarse es solo una pequeña parte de la cadena que el verdadero Internet Explorer 6 envía.</dd>
<dt>YahooCacheSystem</dt>
<dd>Parece ser un robot de Yahoo!, pero por mucho que busqué no logré encontrar información sobre él. Así que al menos por ahora, es un bot desconocido.</dd>
<dt>Firebat</dt>
<dd>Se identifica como: <strong>Firebat 2.7.12</strong><br />
Realmente no encontré nada sobre este robot, más que estadísticas de otros sitios a los que ha visitado.</dd>
</dl>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/Bots">Wikipedia: Bots</a></li>
<li><a href="http://es.wikipedia.org/wiki/Web_crawler">Wikipedia: Web Crawler</a></li>
<li><a href="http://es.wikipedia.org/wiki/RSS">Wikipedia: RSS</a></li>
<li><a href="http://es.wikipedia.org/wiki/Robots.txt">Wikipedia: Robots.txt</a></li>
<li><a href="http://useragentstring.com/">UserAgentString: base de datos de agentes de usuario</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/general/55-bots-servicios-de-internet-y-desconocidos/feed</wfw:commentRss>
	
		<series:name><![CDATA[Conociendo a los Bots]]></series:name>
	</item>
		<item>
		<title>Bots: Programas y publicitarios / corporativos</title>
		<link>http://elcodiguero.com/general/54-bots-programas-publicitarios-corporativos</link>
		<comments>http://elcodiguero.com/general/54-bots-programas-publicitarios-corporativos#comments</comments>
		<pubDate>Thu, 03 Jul 2008 20:27:43 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=54</guid>
		<description><![CDATA[Es incontable la cantidad de programas que por un motivo u otro se conectan a alguna página de internet. La mayoría de ellos son inofensivos, aunque algunos son sospechosos y bien podrían ser robots de los &#034;malos&#034;&#8230;
El problema es que no todos los programas que se conectan a páginas de internet se identifican con su [...]]]></description>
			<content:encoded><![CDATA[<p>Es incontable la cantidad de programas que por un motivo u otro se conectan a alguna página de internet. La mayoría de ellos son inofensivos, aunque algunos son sospechosos y bien podrían ser robots de los &#034;malos&#034;&#8230;<br />
El problema es que no todos los programas que se conectan a páginas de internet se identifican con su verdadero nombre, muchos se identifican simplemente con el nombre de la biblioteca o módulo que usan para establecer la conexión a internet.</p>
<dl>
<dt>BSalsa</dt>
<dd>Se identifica como: <strong>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; TuneUp HTML Client Embedded Web Browser from: http://bsalsa.com/; Alexa Toolbar; MEGAUPLOAD 2.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)</strong> (aunque creo que esto puede cambiar)<br />
<a href="http://bsalsa.com"><em>bsalsa</em></a> es un componente <a href="http://es.wikipedia.org/wiki/Delphi">Delphi</a> para crear aplicaciones con capacidades de navegación en Internet. Se puede ver que el agente de usuario tiene mucha basura, así que no apostaría a que siempre es igual&#8230;</dd>
<dt>CFNetwork</dt>
<dd>Se identifica como: <strong>CFNetwork/330</strong><br />
Por lo que pude encontrar, este es el agente de usuario que envía un programa que hace uso de la función <strong>NSURL</strong>, parte de <a href="http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Introduction/chapter_1_section_1.html#//apple_ref/doc/uid/TP30001132-CH1-DontLinkElementID_24">CFNetwork</a>, que a su vez es parte de las bibliotecas <a href="http://developer.apple.com/cocoa/">Cocoa</a> de Mac OS.</dd>
<dt>Google Desktop</dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; Google Desktop)</strong><br />
Cuando <em>Google Desktop</em> se comunica con algún sitio, se identifica de esta forma. Por lo que sé a veces lo hace para indexar los contenidos RSS</dd>
<dt>Heritrix</dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; heritrix/2.0.0 +(alguna url) )</strong><br />
<a href="http://crawler.archive.org/">Heritrix</a> es el robot desarrollado para el <a href="http://archive.org">Internet Archive</a>. Pero no quiere decir que todas las veces que visite un sitio lo haga por su &#034;creador&#034;: el motor se encuentra disponible para su descarga y uso libre.</dd>
<dt><a href="http://htmlparser.sourceforge.net/">HTMLParser</a></dt>
<dd>Se identifica como: <strong>HTMLParser/1.6</strong><br />
<em>HTMLParser</em> es una biblioteca Java cuyo propósito es el procesamiento de <acronym title="HyperText Markup Language">HTML</acronym>. En la página oficial puede leerse que sus desarrolladores dicen que es una biblioteca &#034;robusta, rápida y bien probada&#034;. Esto implica que muchos programas Java que analicen páginas web harán uso de ella.</dd>
<dt><a href="http://java.sun.com">Java/1.6.0_04</a></dt>
<dd>Cuando no hay ningún cambio en la cabecera correspondiente, los programas Java se identificarán con la versión de la <acronym title="Java Runtime Environment">JRE</acronym> que están usando. En este caso, se trata de programa corriendo sobre la JRE (o <acronym title="Java Development Kit">JDK</acronym>) 1.6.0_04</dd>
<dt><a href="http://larbin.sourceforge.net">Larbin</a></dt>
<dd>Se identifica como: <strong>larbin_2.6.3 larbin2.6.3@unspecified.mail</strong> (el correo varía)<br />
De acuerdo a su propia página web, <em>Larbin</em> es un robot de propósito general, pensado para ser rápido y eficiente mientras recorre las páginas web. No hay mucho que decir sobre él.</dd>
<dt><a href="http://www.linpro.no/lwp/">libwww-perl</a></dt>
<dd>Se identifica como: <strong>libwww-perl/5.805</strong> (donde 5.805 es la versión de Perl)<br />
<em>libwww-perl</em> es un conjunto de módulos de <a href="http://perl.com/">Perl</a> que permite crear clientes <a href="http://es.wikipedia.org/wiki/WWW">WWW</a> con relativa facilidad. Basicamente cualquier programa en Perl que se conecte a algún sitio usará esta biblioteca.</dd>
<dt>Python-urllib</dt>
<dd>Se identifica como: <strong>Python-urllib/1.16</strong><br />
<a href="http://docs.python.org/lib/module-urllib.html">urllib</a> es el nombre del módulo de Python que provee las funciones de cliente <a href="http://es.wikipedia.org/wiki/HTTP">HTTP</a>. Basicamente esto quiere decir que el sitio fue visitado por un programa hecho en <a href="http://www.python.org">Python</a>.</dd>
</dl>
<h3>Publicitarios / Corporativos</h3>
<p>Si bien en internet parece que todo es gratuidad y libertad, también existen los servicios especializados en publicidad y los servicios para empresas. A todos estos robots y servicios los desconocía completamente.</p>
<dl>
<dt><a href="http://panscient.com">Panscient</a></dt>
<dd>Se identifica como: <strong>panscient.com</strong><br />
<em>Panscient</em> es una empresa dedicada a vender servicios de <a href="http://es.wikipedia.org/wiki/Buscador_vertical">búsqueda vertical</a>. No conocía esta clase de servicios hasta que tuve que buscar para saber qué hace este robot, pero la página de Wikipedia está bastante clara.</dd>
<dt><a href="http://www.proximic.com">Proximic</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; proximic; +http://www.proximic.com)</strong><br />
<em>Proximic</em> es una empresa de publicidad que provee anuncios relevantes al contenido de la página.</dd>
<dt><a href="http://www.snap.com">Snapbot</a></dt>
<dd>Se identifica como: <strong>Snapbot/1.0 (Snap Shots, +http://www.snap.com)</strong><br />
<em>Snap.com</em> es un sitio que provee un servicio interesante: para cada enlace de un sitio, provee una captura de pantalla de la página destino, que aparece en un globo por encima del contenido. En el mismo globo añade una caja de búsqueda, porque además se trata de un buscador.</dd>
<dt><a href="http://www.sphere.com">Sphere Scout</a></dt>
<dd>Se identifica como: <strong>Sphere Scout v4.0 - scout at sphere dot com</strong><br />
<em>Sphere</em> es una empresa que provee servicios de publicidad contextual, brinda enlaces a artículos y contenido multimedia relevante (según su criterio) al artículo en el que la publicidad se añade.</dd>
</dl>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/Bots">Wikipedia: Bots</a></li>
<li><a href="http://es.wikipedia.org/wiki/Web_crawler">Wikipedia: Web Crawler</a></li>
<li><a href="http://es.wikipedia.org/wiki/RSS">Wikipedia: RSS</a></li>
<li><a href="http://es.wikipedia.org/wiki/Robots.txt">Wikipedia: Robots.txt</a></li>
<li><a href="http://useragentstring.com/">UserAgentString: base de datos de agentes de usuario</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/general/54-bots-programas-publicitarios-corporativos/feed</wfw:commentRss>
	
		<series:name><![CDATA[Conociendo a los Bots]]></series:name>
	</item>
		<item>
		<title>Bots: Buscadores y lectores de blogs</title>
		<link>http://elcodiguero.com/general/53-bots-buscadores-lectores-de-blogs</link>
		<comments>http://elcodiguero.com/general/53-bots-buscadores-lectores-de-blogs#comments</comments>
		<pubDate>Thu, 03 Jul 2008 17:25:52 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=53</guid>
		<description><![CDATA[Buscadores de blogs
Nada en particular, simplemente sitios y servicios especializados en búsqueda y directorios de blogs.
El más conocido de esta categoría es Technorati.

BlogPulseLive
Se identifica como: BlogPulseLive (support@blogpulse.com)
BlogPulse es un buscador de blogs con funciones estadísticas muy interesantes
Feedfetcher-Google
Se identifica como: Feedfetcher-Google; (+http://www.google.com/feedfetcher.html)
Feedfetcher es el nombre del robot que Google usa para analizar el contenido de los [...]]]></description>
			<content:encoded><![CDATA[<h3>Buscadores de blogs</h3>
<p>Nada en particular, simplemente sitios y servicios especializados en búsqueda y directorios de blogs.<br />
El más conocido de esta categoría es Technorati.</p>
<dl>
<dt><a href="http://www.blogpulse.com">BlogPulseLive</a></dt>
<dd>Se identifica como: <strong>BlogPulseLive (support@blogpulse.com)</strong><br />
<em>BlogPulse</em> es un buscador de blogs con funciones estadísticas muy interesantes</dd>
<dt><a href="http://scholar.google.com/feedfetcher.html">Feedfetcher-Google</a></dt>
<dd>Se identifica como: <strong>Feedfetcher-Google; (+http://www.google.com/feedfetcher.html)</strong><br />
<em>Feedfetcher</em> es el nombre del robot que Google usa para analizar el contenido de los blogs que un usuario haya añadido a su página principal (de Google), o a su cuenta de Google Reader. El contenido indexado por este robot NO afecta el posicionamiento del sitio en los resultados de búsqueda, el encargado de afectar esto es <strong>Googlebot</strong>.</dd>
<dt><a href="http://www.technorati.com">Technoratibot</a></dt>
<dd>Se identifica como: <strong>Technoratibot/0.7</strong><br />
<em>Technorati</em> es el buscador de blogs más grande y conocido. Un sitio muy interesante que vale la pena revisar de vez en cuando.</dd>
<dt><a href="http://www.twingly.com">Twingly Recon</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; Twingly Recon; http://www.twingly.com/)</strong><br />
<em>Twingly</em> es, según su propia página, &#034;Un motor de búsqueda de blogs de la próxima generación, libre de spam&#034;.</dd>
<dt><a href="http://publisher.yahoo.com/rssguide">YahooFeedSeeker</a></dt>
<dd>Se identifica como: <strong>YahooFeedSeeker/2.0 (compatible; Mozilla 4.0; MSIE 5.5; http://publisher.yahoo.com/rssguide)</strong><br />
<em>Yahoo!</em> mantiene una base de datos de &#034;feeds&#034;, este robot se encarga de proveer de contenido a esa base de datos. Además, una vez que el contenido está indexado, los usuarios de Yahoo! pueden añadir nuestro RSS a su página de &#034;My Yahoo!&#034;.</dd>
</dl>
<h3>Lectores / indexadores de RSS</h3>
<p>Los lectores de RSS son aquellos programas (aplicaciones de escritorio o aplicaciones web) que permiten mantenerse al tanto de las novedades de tantos sitios web como se quiera. Se han convertido en parte esencial de la navegación diaria de muchas personas, entre las que me incluyo.</p>
<dl>
<dt><a href="http://www.bloglines.com">BlogLines</a></dt>
<dd>Se identifica como: <strong>Bloglines/3.1 (http://www.bloglines.com)</strong><br />
<em>BlogLines</em> es un lector de RSS en línea, y uno de los mejores. O al menos eso creo yo, ya que es el servicio que uso.</dd>
<dt><a href="http://www.blogsnow.com/">BlogsNowBot</a></dt>
<dd>Se identifica como: <strong>BlogsNowBot, V 3.0 (+http://www.blogsnow.com/)</strong><br />
<em>BlogsNow</em> es un sitio bastante simple, que muestra en una sola página las actualizaciones más recientes de los blogs que tiene registrados. Parece ser más un experimento que un sitio &#034;serio&#034;, y no provee servicios de ningún tipo para los usuarios.</dd>
<dt><a href="http://www.feedburner.com">FeedBurner</a></dt>
<dd>Se identifica como: <strong>FeedBurner/1.0 (http://www.FeedBurner.com)</strong><br />
<em>FeedBurner</em> es un sitio que hace de intermediario entre el <em>feed</em> del sitio y el mundo real. Provee servicios de estadísticas y libera de carga al servidor, ya que los sitios externos hacen todas sus peticiones a los servidores de FeedBurner, y éste último solo obtiene la &#034;copia original&#034; una vez cada cierto tiempo.</dd>
<dt><a href="http://www.feedburner.com">FeedBurner-Email</a></dt>
<dd>Se identifica como: <strong>FeedBurner-Email/1.0</strong><br />
Uno de los servicios que ofrece <em>FeedBurner</em> es la suscripción por correo electrónico a las novedades del sitio. <em>FeedBurner-Email</em> es el robot que usan para mantener actualizada la información de ese servicio.</dd>
<dt><a href="http://www.moreover.com">Moreoverbot</a></dt>
<dd>Se identifica como: <strong>Moreoverbot/5.00 (+http://www.moreover.com)</strong><br />
<em>Moreover</em> provee a las empresas un indexador de contenidos. Tiene características bastante interesantes, pero es simplemente un lector RSS de pago.</dd>
</dl>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/Bots">Wikipedia: Bots</a></li>
<li><a href="http://es.wikipedia.org/wiki/Web_crawler">Wikipedia: Web Crawler</a></li>
<li><a href="http://es.wikipedia.org/wiki/RSS">Wikipedia: RSS</a></li>
<li><a href="http://es.wikipedia.org/wiki/Robots.txt">Wikipedia: Robots.txt</a></li>
<li><a href="http://useragentstring.com/">UserAgentString: base de datos de agentes de usuario</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/general/53-bots-buscadores-lectores-de-blogs/feed</wfw:commentRss>
	
		<series:name><![CDATA[Conociendo a los Bots]]></series:name>
	</item>
		<item>
		<title>¿Cómo escribir un archivo robots.txt?</title>
		<link>http://elcodiguero.com/general/51-como-escribir-un-archivo-robots-txt</link>
		<comments>http://elcodiguero.com/general/51-como-escribir-un-archivo-robots-txt#comments</comments>
		<pubDate>Wed, 02 Jul 2008 01:13:29 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=51</guid>
		<description><![CDATA[Un archivo robots.txt es un archivo de texto simple, que sirve para indicar a los robots (en especial a los robots de los buscadores) qué partes del sitio no debería indexar. Se considera que se puede indexar cualquier carpeta o archivo que no esté explícitamente prohibido por este archivo.
Los buscadores más importantes lo respetan (de [...]]]></description>
			<content:encoded><![CDATA[<p>Un archivo <code class="simple">robots.txt</code> es un archivo de texto simple, que sirve para indicar a los robots (en especial a los robots de los buscadores) qué partes del sitio no debería indexar. Se considera que se puede indexar cualquier carpeta o archivo que no esté explícitamente prohibido por este archivo.</p>
<p>Los buscadores más importantes lo respetan (de otra forma su utilidad sería bastante escasa).</p>
<p>Hay varios motivos para usar un archivo <code class="simple">robots.txt</code>:</p>
<ul>
<li>Evitar el indexado de las imágenes</li>
<li>Evitar que un robot consuma demasiado ancho de banda</li>
<li>Dirigir a los buscadores a las páginas especialmente preparadas para ellos</li>
</ul>
<h2>¿Cómo crearlo?</h2>
<p>El archivo <code class="simple">robots.txt</code> es un archivo de texto simple, que se ubica en la raíz del sitio. El formato del archivo es extremadamente simple, consta de 1 o más conjuntos, separados por una línea en blanco, de:</p>
<ul>
<li>Una línea <code class="simple">User-agent</code>, indicando el nombre de un robot o &#034;*&#034;; (todos los robots).
<p>Si bien la especificación de robotstxt.org no impone que se respeten mayúsculas y minúsculas, para máxima compatibilidad es mejor respetarlas. Esto es: escribir &#034;User-agent&#034; con la U mayúscula, y escribir el nombre del robot tal cual se identifica.</p>
<p>Otro detalle a considerar es que no se aceptan expresiones regulares, solamente el nombre de un robot (y solo uno) o el asterisco &#034;*&#034; para que coincida con todos.</p>
</li>
<li>Una o más líneas <code class="simple">Disallow</code> (no permitir), cada una indicando una carpeta o archivo del sitio que no se quiere que el robot (indicado por la línea User-agent) indexe. En esta línea tampoco se admiten &#034;comodines&#034;, debe darse la ruta completa. Cada línea <em>Disallow</em> debe contener solamente <strong>una</strong> ruta.</li>
</ul>
<p>He aquí un ejemplo, en el que se niega a todos los robots el acceso a la carpeta /admin y al Googlebot el acceso a la carpeta <code class="simple">/imagenes</code> y al archivo <code class="simple">/javascript/ultrasecreto.js</code></p>
<p><code>User-agent: *
Disallow: /admin/

User-agent: Googlebot
Disallow: /imagenes/
Disallow: /javascript/ultrasecreto.js</code></p>
<p>Los robots que respetan sus directivas lo buscan cada vez que se conectan a un servidor, así que si el archivo no existe se generarán muchos errores 404 causados por robots buscándolo.</p>
<h3>¿Cómo saber el nombre que hay que usar para un robot?</h3>
<p>La mayoría de los robots &#034;serios&#034; acompañan su cabecera User Agent con una URL en la que se puede encontrar información sobre ellos, que suele incluir los datos necesarios para &#034;guiar&#034; al robot usando el <code class="simple">robots.txt</code>.</p>
<h2>Seguridad</h2>
<p>Es importante destacar que aunque sirva para indicar a los robots por qué partes del sitio no deben entrar, el archivo <code class="simple">robots.txt</code> no debe ser usado como mecanismo de seguridad. Los robots reciben la indicación de no entrar, pero nada les impide hacerlo.<br />
Además, todas las rutas que se indiquen quedan visibles para cualquiera que quiera verlas, nada impide a cualquier usuario ver el archivo, sobretodo considerando que siempre se encuentra en la misma ubicación (la raíz del sitio).</p>
<p>Si se necesita seguridad, se necesita un sistema basado en programación del lado del servidor, como siempre (ya sea un paquete PHP o autenticación HTTP)</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://elcodiguero.com/general/44-conociendo-a-los-bots" title="Conociendo a los Bots: Buscadores genéricos">Conociendo a los Bots: Buscadores genéricos</a></li>
<li><a href="http://www.robotstxt.org/robotstxt.html">Preguntas frecuentes sobre el archivo robots.txt</a></li>
<li><a href="http://es.wikipedia.org/wiki/Robots.txt">Wikipedia: robots.txt</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://elcodiguero.com/general/51-como-escribir-un-archivo-robots-txt/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
