<?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:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>El Codiguero</title>
	<atom:link href="http://alvlin.com/feed" rel="self" type="application/rss+xml" />
	<link>http://alvlin.com</link>
	<description>Programando para la wé</description>
	<pubDate>Mon, 06 Oct 2008 18:54:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Tipos de coincidencias y referencias</title>
		<link>http://alvlin.com/articulos/99-tipos-coincidencias-referencias</link>
		<comments>http://alvlin.com/articulos/99-tipos-coincidencias-referencias#comments</comments>
		<pubDate>Sat, 27 Sep 2008 03:31:17 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=99</guid>
		<description><![CDATA[Parte 7 de 7 de la serie Expresiones Regulares

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úsquecuantificadores-da de información en cadenas [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 7 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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úsquecuantificadores-da 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://alvlin.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;<br />
vector[1] = &#039;http://alvlin.com&#039;<br />
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://alvlin.com/articulos/99-tipos-coincidencias-referencias/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Cuantificadores</title>
		<link>http://alvlin.com/articulos/95-cuantificadores</link>
		<comments>http://alvlin.com/articulos/95-cuantificadores#comments</comments>
		<pubDate>Fri, 19 Sep 2008 03:09:54 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=95</guid>
		<description><![CDATA[Parte 5 de 7 de la serie Expresiones Regulares

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 5 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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://alvlin.com/articulos/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://alvlin.com/articulos/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<br />
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://alvlin.com/articulos/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://alvlin.com/articulos/85-parentesis-escape-caracteres-alternacion-patrones</link>
		<comments>http://alvlin.com/articulos/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[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=85</guid>
		<description><![CDATA[Parte 5 de 7 de la serie Expresiones Regulares

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 5 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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:<br />
^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://alvlin.com/articulos/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://alvlin.com/articulos/81-clases-caracteres-predefinidas</link>
		<comments>http://alvlin.com/articulos/81-clases-caracteres-predefinidas#comments</comments>
		<pubDate>Thu, 04 Sep 2008 02:32:41 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=81</guid>
		<description><![CDATA[Parte 4 de 7 de la serie Expresiones Regulares

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 4 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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://alvlin.com/articulos/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://alvlin.com/articulos/74-exp-regulares-clases-de-caracteres</link>
		<comments>http://alvlin.com/articulos/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[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=74</guid>
		<description><![CDATA[Parte 3 de 7 de la serie Expresiones Regulares

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 3 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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]<br />
[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://alvlin.com/articulos/74-exp-regulares-clases-de-caracteres/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Metacaracteres: Anclas</title>
		<link>http://alvlin.com/articulos/59-metacaracteres-anclas</link>
		<comments>http://alvlin.com/articulos/59-metacaracteres-anclas#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:52:17 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

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

		<guid isPermaLink="false">http://alvlin.com/?p=59</guid>
		<description><![CDATA[Parte 2 de 7 de la serie Expresiones Regulares

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 2 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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://alvlin.com/articulos/59-metacaracteres-anclas/feed</wfw:commentRss>
	
		<series:name><![CDATA[Expresiones Regulares]]></series:name>
	</item>
		<item>
		<title>Expresiones regulares: Introducción</title>
		<link>http://alvlin.com/articulos/56-expresiones-regulares-introduccion</link>
		<comments>http://alvlin.com/articulos/56-expresiones-regulares-introduccion#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:24:20 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<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[<div class="seriesmeta">Parte 1 de 7 de la serie <a href="http://alvlin.com/series/expresiones-regulares" title="series-122">Expresiones Regulares</a></div>

<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://alvlin.com/articulos/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://alvlin.com/varios/55-bots-servicios-de-internet-y-desconocidos</link>
		<comments>http://alvlin.com/varios/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]]></category>

		<category><![CDATA[Varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=55</guid>
		<description><![CDATA[Parte 4 de 4 de la serie Conociendo a los Bots

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 4 de 4 de la serie <a href="http://alvlin.com/series/conociendo-a-los-bots" title="series-121">Conociendo a los Bots</a></div>

<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://alvlin.com/varios/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://alvlin.com/varios/54-bots-programas-publicitarios-corporativos</link>
		<comments>http://alvlin.com/varios/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]]></category>

		<category><![CDATA[Varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=54</guid>
		<description><![CDATA[Parte 3 de 4 de la serie Conociendo a los Bots

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 3 de 4 de la serie <a href="http://alvlin.com/series/conociendo-a-los-bots" title="series-121">Conociendo a los Bots</a></div>

<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://alvlin.com/varios/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://alvlin.com/varios/53-bots-buscadores-lectores-de-blogs</link>
		<comments>http://alvlin.com/varios/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]]></category>

		<category><![CDATA[Varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=53</guid>
		<description><![CDATA[Parte 2 de 4 de la serie Conociendo a los Bots

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 [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 2 de 4 de la serie <a href="http://alvlin.com/series/conociendo-a-los-bots" title="series-121">Conociendo a los Bots</a></div>

<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://alvlin.com/varios/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://alvlin.com/varios/51-como-escribir-un-archivo-robots-txt</link>
		<comments>http://alvlin.com/varios/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]]></category>

		<category><![CDATA[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: *<br />
Disallow: /admin/</p>
<p>User-agent: Googlebot<br />
Disallow: /imagenes/<br />
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://alvlin.com/varios/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://alvlin.com/varios/51-como-escribir-un-archivo-robots-txt/feed</wfw:commentRss>
		</item>
		<item>
		<title>Validar una dirección de correo electrónico con PHP</title>
		<link>http://alvlin.com/php/50-validar-una-direccion-de-correo-electronico-con-php</link>
		<comments>http://alvlin.com/php/50-validar-una-direccion-de-correo-electronico-con-php#comments</comments>
		<pubDate>Thu, 12 Jun 2008 03:35:57 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=50</guid>
		<description><![CDATA[Esta pregunta es bastante frecuente, cualquier sistema que utilice el correo electrónico debería tener algún tipo de validación para evitar errores y datos basura.
Antes que nada hay que tener por seguro que no hay forma (rápida y práctica) de comprobar que una dirección de correo existe y tiene a un usuario detrás, solamente se puede [...]]]></description>
			<content:encoded><![CDATA[<p>Esta pregunta es bastante frecuente, cualquier sistema que utilice el correo electrónico debería tener algún tipo de validación para evitar errores y datos basura.<br />
Antes que nada hay que tener por seguro que no hay forma (rápida y práctica) de comprobar que una dirección de correo existe y tiene a un usuario detrás, solamente se puede comprobar que la dirección tiene una forma válida y apunta a un dominio activo.</p>
<p>Hay varias formas de encarar el problema, como suele suceder. Hay sistemas que simplemente validan que la información ingresada contenga una arroba, hay otros que usan expresiones regulares complejas que fallan en cuanto la dirección ingresada no es &#034;común&#034; (aunque sea válida).<br />
La forma que voy a plantear no es novedosa, y es bastante sencilla, a la vez que efectiva.</p>
<h2>Una expresión regular permisiva</h2>
<p>Y con &#034;permisiva&#034;, me refiero a que debe poder validar a cualquier dirección de correo válida, esto quiere decir que debe ser también bastante genérica.<br />
El patrón debe validar que exista una arroba, un nombre de usuario, y una parte que indique el dominio.<br />
A pesar de que probablemente nunca se usen nombres de usuario complejos en una dirección de correo, la verdad es que se puede usar cualquier caracter en esta parte de la dirección.<br />
Por lo que la expresión regular que debe validar esto no puede ser otra que<br />
<code>.+</code><br />
Que simplemente indica &#034;al menos 1 caracter&#034;.</p>
<p>El dominio es un poco más complicado. Muchos cometen el error de solamente permitir dos o tres partes separadas por punto, o rechazar direcciones cuya última parte contenga más de 3 caracteres. Con esto se supone que incluyen a todos los dominios de primer nivel (.com, .net, .org&#8230; y los de los países, que tienen 2 letras). Pero se olvidan que Internet cambia, y ya tenemos <a href="http://es.wikipedia.org/wiki/TLD"><acronym title="Top Level Domain - Dominio de Nivel Superior">TLD</acronym></a> .info (de cuatro letras) e incluso .museum.<br />
Así que en esta parte hay que ser permisivos. Más aún si se considera que lentamente están apareciendo los dominios con &#034;ñ&#034; y demás letras españolas, y que quizás pronto las direcciones comiencen a aceptar más caracteres <a href="http://es.wikipedia.org/wiki/UTF-8">UTF-8</a>.</p>
<p>Así que el patrón para validar el dominio es simple: al menos 2 secuencias de caracteres separadas por un punto. No puede haber un dominio que sea solamente una palabra, ya que se trataría de direcciones de red local. Estas direcciones son perfectamente válidas en una red local, pero no en internet.<br />
<code>.+\..+</code><br />
Este patrón indica: &#034;una secuencia de caracteres no vacía, seguida de un punto, y seguida de otra secuencia de caracteres no vacía&#034;.</p>
<p>Juntando las partes, el patrón queda:<br />
<code>^.+@.+\..+$</code></p>
<h2>Validación del dominio</h2>
<p>Una versión anterior de este artículo recomendaba validar el dominio con <a href="http://php.net/checkdnsrr">checkdnsrr()</a>. Esta parte ha sido eliminada. El motivo es bastante simple, a decir verdad.</p>
<p>La función <em>checkdnsrr</em> solamente puede determinar si un dominio tiene un registro <a href="http://es.wikipedia.org/wiki/DNS"><acronym title="Domain Name System - Sistema de Nombres de Dominio">DNS</acronym></a> asociado. Esto no implica que el servidor esté activo (o que haya un servidor de correo en el dominio).<br />
Otras opciones, como <a href="http://php.net/gethostbyname">gethostbyname</a> por ejemplo, tienen sus propios problemas:</p>
<ul>
<li>Pueden fallar si el servidor remoto está temporalmente fuera de servicio, lo cual no es tan extraño en servidores pequeños.</li>
<li>Si el <em>host</em> remoto no existe, la llamada a <em>gethostbyname</em> demora mucho en completarse, no por PHP sino por la forma en la que funciona el protocolo DNS.</li>
<li>Podría haber un fallo de conectividad temporal de parte del servidor que ejecuta el programa PHP, lo cual provocaría que la función fallase.</li>
</ul>
<p>Por estos motivos es que la validación del dominio funcionará en la mayoría de los casos pero fallará en otros. Y si no se puede saber que será exitosa en <strong>todos</strong> los casos, no se puede confiar en ella.</p>
<p>De todas formas se incluyen los enlaces a las páginas del manual de PHP que corresponden a estas funciones, para que cada uno decida si hacer la validación o no.</p>
<p>Vale recordar lo que se mencionó al principio: no existe forma práctica de comprobar con certeza que la dirección es válida aún cuando se pudiese validar el dominio, dado que la dirección podría ser válida en forma pero no existir en el servidor, o podría estar mal escrita por error.<br />
La única manera de saber con seguridad si la dirección es válida es enviar un correo de confirmación antes de habilitar al usuario a continuar en el sitio. Pero esto tampoco es la solución en todos los casos; a veces solicitar confirmación al usuario no tiene sentido (por ejempo en un formulario de contacto).</p>
<p>He aquí entonces, el código de la función completa:<br />
<code class="prettyprint">function validarCorreo($correo) {<br />
    return <a href="http://php.net/ereg">ereg</a>(&#039;^.+@(.+\..+)$&#039;, $correo);<br />
}</code></p>
<p>A modo de resumen: la validación de direcciones de correo es compleja y no vale la pena intentar validar más que la forma. La mayoría de los métodos más estrictos con los que uno se puede llegar a encontrar suelen rechazar direcciones perfectamente correctas (aunque relativamente raras).</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/TLD">Wikipedia: <acronym title="Top Level Domain - Dominio de Nivel Superior">TLD</acronym></a></li>
<li><a href="http://es.wikipedia.org/wiki/UTF-8">Wikipedia: UTF-8</a></li>
<li><a href="http://es.wikipedia.org/wiki/DNS">Wikipedia: DNS</a></li>
<li><a href="http://es.wikipedia.org/wiki/Expresiones_regulares">Wikipedia: Expresiones regulares</a></li>
<li><a href="http://php.net/checkdnsrr">PHP: checkdnsrr()</a></li>
<li><a href="http://php.net/gethostbyname">PHP: gethostbyname</a></li>
<li><a href="http://php.net/ereg">PHP: ereg</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/php/50-validar-una-direccion-de-correo-electronico-con-php/feed</wfw:commentRss>
		</item>
		<item>
		<title>Imágenes de CD: formatos y conversiones</title>
		<link>http://alvlin.com/articulos/49-imagenes-de-cd-formatos-y-conversiones-2</link>
		<comments>http://alvlin.com/articulos/49-imagenes-de-cd-formatos-y-conversiones-2#comments</comments>
		<pubDate>Sun, 25 May 2008 23:46:52 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=49</guid>
		<description><![CDATA[Normalmente uso el K3B para todo lo que tenga que ver con grabación de cd/dvd. También normalmente, como costumbre que adquirí­ quién sabe cuándo, grabo las imágenes como &#034;copia clon&#034;. Esto se supone que crea una imagen exactamente igual al cd original.
Cuando quise montar una de esas imágenes para no tener que grabarla en un [...]]]></description>
			<content:encoded><![CDATA[<p>Normalmente uso el <a href="http://k3b.sf.net">K3B</a> para todo lo que tenga que ver con grabación de cd/dvd. También normalmente, como costumbre que adquirí­ quién sabe cuándo, grabo las imágenes como &#034;copia clon&#034;. Esto se supone que crea una imagen exactamente igual al cd original.</p>
<p>Cuando quise montar una de esas imágenes para no tener que grabarla en un cd, el comando normal para estas tareas<br />
<code>mount -t iso9660 archivo.iso punto_de_montaje -o loop</code><br />
no me sirvió para nada. La respuesta fue &#034;check dmesg output&#034; (&#034;fijate en dmesg&#034;), y dmesg solamente tení­a un mensaje:<br />
<strong>Unable to identify CD-ROM format.</strong></p>
<p>&#034;Muy bien&#034;, pensé. &#034;Tendré que encontrar alguna forma de convertir esto&#034;.</p>
<p>Como la había grabado con el K3B, pensé en cargarla con el mismo programa a ver qué información me daba. Según K3B la imagen es de tipo &#034;Imagen clon cd-record&#034;, o &#034;cdrecord clone image&#034;. Bien, ¿y ahora qué?</p>
<p>La búsqueda me llevó por varias utilidades: <a href="http://he.fi/bchunk/">bchunk</a>, <a href="http://cdemu.sourceforge.net/">cdemu</a>, <a href="http://kiso.sf.net">kiso</a>, <a href="http://sourceforge.net/projects/ccd2iso">ccd2iso</a> y a páginas como esta: <a href="http://linuxreviews.org/howtos/cdrecording/">CD ripping and burning from the command prompt</a>, o ésta: <a href="http://wiki.linuxquestions.org/wiki/CD_Image_Conversion">CD Image Conversion</a>, donde se mencionan algunas otras utilidades.</p>
<p>Sin embargo, KISO no &#034;QUISO&#034; compilarse, a pesar de tener todas las dependencias resueltas. CDEmu necesita el código fuente de Linux, y no tenía ganas de instalarlo. Las demás utilidades, al menos las que probé (ccd2iso y bchunk) no me funcionaron.</p>
<p>Ya me estaba empezando a convencer de que iba a necesitar grabar en discos &#034;reales&#034; para poder ver los archivos, hasta que la búsqueda me llevó a <a href="http://www.linuxquestions.org/questions/showthread.php?p=2899172">LinuxQuestions</a>.<br />
Muchas veces he &#034;aterrizado&#034; en ese sitio y la verdad es que no tengo dudas de que es el mejor foro sobre Linux que existe.</p>
<p>En el hilo al que me llevó la búsqueda, se menciona otra pequeña utilidad: el <a href="http://iat.berlios.de/">iat, Iso9660 Analyzer Tool</a>. La descargué y la probé con el siguiente comando:<br />
<code>iat diablo2_Install.iso diablo2Install.iso</code></p>
<p>o sea,</p>
<p><code>iat  imagen_original nombre_imagen_convertida</code></p>
<p>Bueno, sí­, ahora queda claro qué cd querí­a convertir <img src='http://alvlin.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>El caso es que 1 minuto más tarde, tení­a la imagen de CD montada y la instalación del Diablo 2 corriendo en mi Slackware 12</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://k3b.sf.net">K3B</a></li>
<li><a href="http://he.fi/bchunk/">bchunk</a></li>
<li><a href="http://cdemu.sourceforge.net/">cdemu</a></li>
<li><a href="http://kiso.sf.net">kiso</a></li>
<li><a href="http://sourceforge.net/projects/ccd2iso">ccd2iso</a></li>
<li><a href="http://linuxreviews.org/howtos/cdrecording/">CD ripping and burning from the command prompt</a></li>
<li><a href="http://wiki.linuxquestions.org/wiki/CD_Image_Conversion">LinuxQuestions: CD Image Conversion</a></li>
<li><a href="http://www.linuxquestions.org/questions/showthread.php?p=2899172">LinuxQuestions: discusión en la que se menciona a IAT</a></li>
<li><a href="http://iat.berlios.de/">iat, Iso9660 Analyzer Tool</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/articulos/49-imagenes-de-cd-formatos-y-conversiones-2/feed</wfw:commentRss>
		</item>
		<item>
		<title>Validar parámetros enteros con PHP</title>
		<link>http://alvlin.com/php/48-validar-parametros-enteros-con-php</link>
		<comments>http://alvlin.com/php/48-validar-parametros-enteros-con-php#comments</comments>
		<pubDate>Sun, 25 May 2008 23:07:54 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=48</guid>
		<description><![CDATA[Introducción
¿Cómo hacer para estar seguro de que un parámetro obtenido por GET (o POST) es un número entero?
Intentando resolver esta pregunta he intentado varias técnicas a lo largo del tiempo, y haciendo esas pruebas he llegado a entender más sobre cómo funcionan las comparaciones y las conversiones automáticas de tipos en PHP.
Lo primero que hay [...]]]></description>
			<content:encoded><![CDATA[<h2>Introducción</h2>
<p>¿Cómo hacer para estar seguro de que un parámetro obtenido por GET (o POST) es un número entero?<br />
Intentando resolver esta pregunta he intentado varias técnicas a lo largo del tiempo, y haciendo esas pruebas he llegado a entender más sobre cómo funcionan las comparaciones y las conversiones automáticas de tipos en PHP.</p>
<p>Lo primero que hay que considerar es que no sirve usar una conversión directa con <em>(int)</em>, o <em>intval()</em>, ya que si bien estaría seguro de que el valor obtenido es entero, eso no quiere decir que sea un valor válido, ya que cualquier cadena puede convertirse a entero (si no comienza con números, su valor es cero). Ante la duda, nada mejor que consultar la página sobre <a href="http://www.php.net/manual/es/language.types.type-juggling.php">manipulación de tipos</a> del manual de PHP.</p>
<h2>Primer intento: is_int</h2>
<p>La primera idea es comprobar con la función <a href="http://www.php.net/is_int">is_int</a>.<br />
Sin embargo, esto no funciona, porque PHP considera <strong>cadenas</strong> a estas variables.<br />
¿Cómo lo sé? Por 2 motivos:</p>
<ol>
<li>La propia página del manual lo advierte: &#034;Para probar si una variable es un número o una cadena numérica (como en el caso de la entrada de un formulario, que es siempre una cadena), debe usar is_numeric()&#034;.</li>
<li><code>gettype($_GET['uno']);</code><br />
Devuelve &#034;string&#034;, aunque el valor de $_GET['uno'] sea 12, por ejemplo.<br />
<code>is_int($_GET['uno']);</code><br />
Devuelve false, en el mismo caso que el anterior.</li>
</ol>
<h2>Segundo intento: is_numeric</h2>
<p><a href="http://www.php.net/is_numeric">is_numeric</a> serviría, excepto porque también acepta números con coma (punto, en realidad). De nuevo, podríamos simplemente convertirlo a entero con (int), pero no sería el valor original y por lo tanto no sería un valor válido.</p>
<h2>Tercer intento: comparación con entero</h2>
<p>Otra opción puede ser hacer una comparación como<br />
<code>$_GET['var'] == (int) $_GET['var'];</code></p>
<p>En teoría funcionaría, pero no es así.<br />
PHP es un tanto &#034;especial&#034; en lo que refiere a las conversiones de tipos: siempre que haya un entero en un lado de la comparación, convertirá el otro lado en entero.<br />
Por lo tanto, la comparación SIEMPRE será cierta, ya que el lado izquierdo de la comparación será convertido también, resultando en lo mismo que si escribiese<br />
<code class="prettyprint">(int) $_GET['var'] == (int) $_GET['var'];</code></p>
<h2>Cuarto intento: comparación de idénticos</h2>
<p>Bueno, si PHP convierte a entero ambos lados y por eso no sirve el ejemplo anterior, bastaría con usar el comparador ===, ¿no?<br />
¡NO! Porque siempre serán de tipos diferentes, ya que como se dijo antes, las variables GET son tomadas como cadenas.</p>
<h2>Quinto intento: complicado pero funciona</h2>
<p>Finalmente decidí ir por algo más complejo pero que evita todos los problemas de los casos anteriores.<br />
¿Qué hacer? La comparación con un entero es necesaria, porque después de todo lo que necesitamos es un entero, pero no podemos comparar una cadena con un entero porque la cadena será convertida&#8230;<br />
La solución que se me ocurrió es simplemente volver a convertir al entero en una cadena:</p>
<p><code class="prettyprint">$_GET['var'] == (string) intval($_GET['var']);</code></p>
<p>Luego de mucho experimentar, la anterior es la mejor solución que he encontrado.<br />
Me gustaría saber si por ahí existe una solución mejor.</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://www.php.net/manual/es/language.types.type-juggling.php">Manipulación de tipos en PHP</a></li>
<li><a href="http://www.php.net/is_int">PHP: is_int</a></li>
<li><a href="http://www.php.net/is_numeric">PHP: is_numeric</a></li>
<li><a href="http://www.php.net/gettype">PHP: gettype</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/php/48-validar-parametros-enteros-con-php/feed</wfw:commentRss>
		</item>
		<item>
		<title>Conociendo a los Bots: Buscadores genéricos</title>
		<link>http://alvlin.com/varios/44-conociendo-a-los-bots</link>
		<comments>http://alvlin.com/varios/44-conociendo-a-los-bots#comments</comments>
		<pubDate>Sat, 24 May 2008 01:45:41 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<category><![CDATA[Varios]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=44</guid>
		<description><![CDATA[Parte 1 de 4 de la serie Conociendo a los Bots

Los &#034;bots&#034;, &#034;robots&#034;, &#034;spiders&#034; (arañas) o &#034;crawlers&#034; son los programas que van por la internet de página en página, analizando su contenido para diferentes propósitos.
Los hay &#034;buenos&#034;, como los de los buscadores que luego nos redirigirán visitas, y &#034;malos&#034;, como los que buscan direcciones de [...]]]></description>
			<content:encoded><![CDATA[<div class="seriesmeta">Parte 1 de 4 de la serie <a href="http://alvlin.com/series/conociendo-a-los-bots" title="series-121">Conociendo a los Bots</a></div>

<p>Los &#034;<a href="http://es.wikipedia.org/wiki/Bots">bots</a>&#034;, &#034;robots&#034;, &#034;spiders&#034; (arañas) o &#034;<a href="http://es.wikipedia.org/wiki/Web_crawler">crawlers</a>&#034; son los programas que van por la internet de página en página, analizando su contenido para diferentes propósitos.</p>
<p>Los hay &#034;buenos&#034;, como los de los buscadores que luego nos redirigirán visitas, y &#034;malos&#034;, como los que buscan direcciones de correo para luego enviar correo basura. Por lo general son beneficiosos, y al menos a mí me parece interesante saber de dónde vienen y qué hacen, así que recopilé la lista de los robots que han visitado este sitio y busqué algo de información sobre cada uno.<br />
No pretendo hacer aquí una lista exhaustiva de todos los robots que andan por internet, pero creo que mencionaré los más comunes.</p>
<p>Para estructurar mejor la lista, la he dividido en categorías: Buscadores genéricos, buscadores de blogs, Lectores de <a href="http://es.wikipedia.org/wiki/RSS"><acronym title="Really Simple Sindication">RSS</acronym></a> y Programas.</p>
<h3>Buscadores genéricos y portales</h3>
<p>Los buscadores son los que hoy en día ponen las reglas en Internet. Liderados por <em>Google</em>, parece que todo el mundo busca obtener su bendición y aparecer en los primeros puestos.<br />
Al contrario de lo que pueda parecer hay muchísimos buscadores y portales diferentes, muchos de ellos dirigidos a la gente de un solo país (WebAlta, o Baidu).</p>
<dl>
<dt><a href="http://about.ask.com/en/docs/about/webmasters.shtml">Ask Jeeves/Teoma</a></dt>
<dd>Se identifica como: <strong>Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://about.ask.com/en/docs/about/webmasters.shtml)</strong><br />
<em>Ask</em> es una &#034;empresa de internet&#034; con muchos servicios, bastante grande y conocida. <em>Ask Jeeves</em> es el nombre de su buscador. No es tan conocida en los países hispanos, pero es uno de los grandes en Estados Unidos.</dd>
<dt><a href="http://www.baidu.com/search/spider_jp.html">Baiduspider</dt>
<dd>Se identifica como: <strong>Baiduspider+(+http://www.baidu.com/search/spider_jp.html)</strong><br />
<em>Baidu</em> es el buscador más importante de China. No es muy útil para los que no podemos leer idiogramas, así como probablemente un sitio en español no sea muy útil para el buscador.</dd>
<dt><a href="http://ws.daum.net/aboutkr.html">Daumoa</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; Firefox or MSIE mutant; not on Windows server; +http://ws.daum.net/aboutkr.html) Daumoa/2.0 Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt; DTS Agent</strong><br />
<a href="http://ws.daum.net/abouten.html"><em>Daumoa</em></a> es el nombre del robot del portal <a href="http://en.wikipedia.org/wiki/Daum"><em>Daum</em></a>, un portal del estilo de <em>Yahoo!</em> muy conocido en Corea del Sur. No pude encontrar mucha más información sobre él, dado que el sitio está completamente en coreano.</dd>
<dt><a href="http://discoveryengine.com/discobot.html">discobot</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; discobot/1.0; +http://discoveryengine.com/discobot.html)</strong><br />
<em>DiscoveryEngine</em> es un motor de búsqueda &#034;de próxima generación&#034;, aún en desarrollo. Aunque aún no funciona, su robot anda por ahí analizando páginas.</dd>
<dt><a href="http://www.geona.com/">Geonabot</a></dt>
<dd>Se identifica como: <strong>GeonaBot/1.2; http://www.geona.com/</strong><br />
<em>Geona</em> no tiene una gran base de datos (una búsqueda por &#034;alvlin&#034; solamente devuelve este sitio, no devuelve <a href="http://www.forosdelweb.com">ForosDelWeb</a> por ejemplo) y extrañamente incluye publicidad de Google.</dd>
<dt><a href="http://www.gigablast.com/spider.html">Gigabot</a></dt>
<dd>Se identifica como: <strong>Gigabot/1.0 Gigabot/3.0 (http://www.gigablast.com/spider.html)</strong><br />
<em>Gigablast</em> es un buscador &#034;nuevo&#034;, que da resultados bastante decentes.</dd>
<dt><a href="http://www.google.com/bot.html">Googlebot</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)</strong><br />
El robot de <em>Google</em>. No hay mucho que comentar, dado que es el programa responsable de que un sitio esté indexado en el que en la actualidad es el mayor buscador del mundo</dd>
<dt><a href="http://www.google.com/bot.html">Googlebot-Image</a></dt>
<dd>Se identifica como: <strong>Googlebot-Image/1.0</strong><br />
Se trata del buscador de imágenes de <em>Google</em>.</dd>
<dt><a href="http://www.metadatalabs.com/mlbot">MLBot</a></dt>
<dd>Se identifica como: <strong>MLBot (www.metadatalabs.com/mlbot)</strong><br />
<em>metadatalabs</em> es el nombre de un buscador de contenido multimedia, aún en desarrollo.</dd>
<dt><a href="http://search.msn.com/msnbot.htm">msnbot</a></dt>
<dd>Se identifica como: <strong>msnbot/1.1 (+http://search.msn.com/msnbot.htm)</strong><br />
Este es el robot &#034;genérico&#034; de <em>Live Search</em> (anteriormente MSN). Nada más ni nada menos que el 3º buscador más usado del mundo.</dd>
<dt><a href="http://search.msn.com/msnbot.htm">msnbot-media</a></dt>
<dd>Se identifica como: <strong>msnbot-media/1.0 (+http://search.msn.com/msnbot.htm)</strong><br />
Este es el buscador de contenido multimedia de <em>Live Search</em>.</dd>
<dt><a href="http://www.scoutjet.com">ScoutJet</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; ScoutJet; +http://www.scoutjet.com/)</strong><br />
Como se puede leer en su sitio, <em>ScoutJet</em> es el motor de un nuevo buscador creado por la misma gente que creó <a href="http://www.dmoz.org/World/Español/">DMOZ</a>. El buscador aún no está operativo.</dd>
<dt><a href="http://www.webalta.net/ru/about_webmaster.html">WebAlta Crawler</a></dt>
<dd>Se identifica como: <strong>WebAlta Crawler/2.0 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)</strong><br />
El robot de <em>WebAlta</em>, el buscador más grande y popular de Rusia. Sin embargo, es un robot bastante molesto porque la dirección de información que provee no lleva a ningún lado, y por lo que he leído ni siquiera respeta lo que se especifica en el archivo <a href="http://es.wikipedia.org/wiki/robots.txt">robots.txt</a>. El único de esta lista del que realmente tengo motivos para desconfiar.</dd>
<dt><a href="http://help.yahoo.com/help/us/ysearch/slurp">Yahoo! Slurp</a></dt>
<dd>Se identifica como: <strong>Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) </strong> o<br />
<strong>Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)</strong><br />
el &#034;chupador&#034; (traducción literal de &#034;slurp&#034;) es el robot que <em>Yahoo!</em> usa para indexar las páginas. </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://alvlin.com/varios/44-conociendo-a-los-bots/feed</wfw:commentRss>
	
		<series:name><![CDATA[Conociendo a los Bots]]></series:name>
	</item>
		<item>
		<title>Colores predefinidos en CSS</title>
		<link>http://alvlin.com/articulos/39-colores-predefinidos-en-css</link>
		<comments>http://alvlin.com/articulos/39-colores-predefinidos-en-css#comments</comments>
		<pubDate>Sun, 27 Apr 2008 16:30:45 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Artículos]]></category>

		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://alvlin.com/?p=39</guid>
		<description><![CDATA[CSS provee varias formas de definir colores como valores de propiedades (fondo, color de letra, bordes, etc). Estas son:

rgb(RRR,GGG,BBB)
Valores decimales para rojo, verde y azul, cada uno entre 0 y 255.
rgb(RR%, GG%, BB%)
Valores en porcentajes de rojo, verde y azul. Indicar 0% es igual a poner 0 en la forma anterior, e indicar 100% es [...]]]></description>
			<content:encoded><![CDATA[<p><acronym title="Cascade Style Sheets - Hoja de estilos en cascada">CSS</acronym> provee varias formas de definir colores como valores de propiedades (fondo, color de letra, bordes, etc). Estas son:</p>
<dl>
<dt>rgb(RRR,GGG,BBB)</dt>
<dd>Valores decimales para rojo, verde y azul, cada uno entre 0 y 255.</dd>
<dt>rgb(RR%, GG%, BB%)</dt>
<dd>Valores en porcentajes de rojo, verde y azul. Indicar 0% es igual a poner 0 en la forma anterior, e indicar 100% es lo mismo que poner 255.</dd>
<dt>#RRGGBB</dt>
<dd>valores hexadecimales (tal y como se usan en HTML)</dd>
<dt>#RGB</dt>
<dd>Valores hexadecimales abreviados. Por ejemplo, #FFFFFF (blanco) se puede escribir como #FFF</dd>
<dt>color</dt>
<dd>Uno de los 16 <a href="http://www.sidar.org/recur/desdi/traduc/es/css/syndata.html#color-units">colores predefinidos por la norma CSS</a>.</dt>
</dl>
<p>Esta última opción es la más cómoda, pero también provoca algunos problemas: muchas veces uno prueba el nombre de un color cualquiera (por ejemplo &#034;skyblue&#034;, celeste), ve que funciona, y sigue diseñando tranquilamente. Pero al validar, el validador indica que &#034;skyblue&#034; no es un valor válido&#8230;<br />
Es bueno entonces tener una lista de los colores predefinidos, para evitar estos detalles.</p>
<p>Y los colores predefinidos en CSS2 son los siguientes:</p>
<table style="width: 80%; margin-left : auto; margin-right : auto; text-align : center">
<tr>
<td style="background : white" title="white">white</td>
<td style="background : black" title="black">black</td>
<td style="background : aqua" title="aqua">aqua</td>
<td style="background : blue" title="blue">blue</td>
</tr>
<tr>
<td style="background : fuchsia" title="fuchsia">fuchsia</td>
<td style="background : gray" title="gray">gray</td>
<td style="background : green" title="green">green</td>
<td style="background : lime" title="lime">lime</td>
</tr>
<tr>
<td style="background : maroon" title="maroon">maroon</td>
<td style="background : navy" title="navy">navy</td>
<td style="background : olive" title="olive">olive</td>
<td style="background : purple" title="purple">purple</td>
</tr>
<tr>
<td style="background : red" title="red">red</td>
<td style="background : silver" title="silver">silver</td>
<td style="background : teal" title="teal">teal</td>
<td style="background : yellow" title="yellow">yellow</td>
</tr>
</table>
<p>No son muchos, pero son bastante variados. Y siempre es más cómodo escribir<br />
<strong>white</strong><br />
que<br />
<strong>rgb(255,255,255)</strong></p>
<p>CSS3 promete muchas más opciones a la hora de <a href="http://www.w3.org/TR/css3-color/">manejar los colores</a>. Se podrá elegir el perfil de color, usar los colores predefinidos para SVG, y algunas otras cosas más.</p>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://www.sidar.org/recur/desdi/traduc/es/css/cover.html">CSS2, especificación en español</a></li>
<li><a href="http://www.sidar.org/recur/desdi/traduc/es/css/syndata.html#color-units">CSS2: colores predefinidos.</a></li>
<li><a href="http://www.w3.org/TR/css3-color/">CSS3 Color Module</a></li>
<li><a href="http://bjkeefe.com/ref/valid-html-css-color-names.html">Tabla con los colores válidos y el contraste entre ellos</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/articulos/39-colores-predefinidos-en-css/feed</wfw:commentRss>
		</item>
		<item>
		<title>CSV: simple y versátil</title>
		<link>http://alvlin.com/php/4-csv-simple-y-versatil</link>
		<comments>http://alvlin.com/php/4-csv-simple-y-versatil#comments</comments>
		<pubDate>Tue, 01 Apr 2008 01:29:50 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<category><![CDATA[Varios]]></category>

		<guid isPermaLink="false">http://localhost/?p=4</guid>
		<description><![CDATA[Los archivos CSV son muy simples y permiten crear archivos para ser abiertos en programas de hoja de cálculo de manera muy sencilla. Vale la pena conocer su estructura y los detalles que conciernen a su creación.]]></description>
			<content:encoded><![CDATA[<h2>¿Qué es un archivo CSV?</h2>
<p>Los <a href="http://es.wikipedia.org/wiki/CSV"><acronym title="Comma Separated Values">CSV</acronym></a> son archivos de &#034;valores separados por comas&#034; (de ahí su nombre), es un formato bien simple y práctico.<br />
No tiene una documentación oficial, pero buscando en internet encontré el <a href="http://www.rfc-editor.org/rfc/rfc4180.txt">RFC 4180, “Common Format and MIME Type for Comma-Separated Values (CSV) Files”</a>. Al contrario de muchos RFC, que son especificaciones completas de formatos y protocolos, este parece ser simplemente un resumen de las características de los csv, y un intento por documentar formalmente el formato.</p>
<p>Hay 5 reglas básicas que definen un archivo CSV, a saber:</p>
<ol>
<li>Cada campo se separa con una coma, al último de la fila no le sigue una coma</li>
<li>No se toman en cuenta posibles espacios entre las comas separadoras.</li>
<li>Cada fila se separa con un salto de línea (CRLF, aunque se soporta también LF)</li>
<li>Los campos pueden o no estar delimitados por ” (necesario en particular cuando se necesita incluir una coma en el campo o un salto de línea).</li>
<li>Si se necesita incluir comillas &#034;, hay que duplicarlas: para que se tome &#034;b&#034; como el campo completo, hay que escribirlo como &#034;&#034;b&#034;"</li>
</ol>
<h2>Detalles</h2>
<p>En caso de querer ponerlo para descargar, es bueno saber que el tipo <acronym title="Multipurpose Internet Mail Extensions">MIME</acronym> del formato es <strong>text/csv</strong>.<br />
La codificación de caracteres por defecto se toma como <strong>US-ASCII</strong>, pero puede usarse el parámetro &#034;charset&#034; de la cabecera &#039;<em>Content-Type</em>&#039; para especificar otra. Si no se usa &#034;charset&#034;, el programa que trabaje con el archivo CSV deberá decidir qué codificación usa.<br />
Este es el caso más común, ya que cuando uno abre el archivo con un programa como Excel u <a href="http://www.openoffice.org/">OpenOffice</a> Calc, no existe una cabecera que indique el tipo MIME.</p>
<p>PHP provee 2 funciones, <a href="http://www.php.net/fputcsv">fputcsv</a> y <a href="http://www.php.net/fgetcsv">fgetcsv</a> para manejo de estos archivos.<br />
<strong>fgetcsv</strong> extrae los campos separados por comas de un archivo, línea por línea, mientras que <strong>fgetcsv</strong> permite hacer el proceso contrario.</p>
<p>En resumen, CSV es un formato simple y versátil, útil cuando se trata de transmitir información que no requiera un procesamiento complejo. En caso de requerirlo, quizás el formato <a href="http://es.wikipedia.org/wiki/XML"><acronym title="eXtensible Markup Language">XML</acronym></a> o  <a href="http://es.wikipedia.org/wiki/JSON"><acronym title="JavaScript Object Notation">JSON</acronym></a> sea más apropiado.</p>
<h4 class="relacionados">Enlaces relacionados:</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/CSV">Wikipedia: CSV</a></li>
<li><a href="http://www.rfc-editor.org/rfc/rfc4180.txt">RFC 4180, “Common Format and MIME Type for Comma-Separated Values (CSV) Files”</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/php/4-csv-simple-y-versatil/feed</wfw:commentRss>
		</item>
		<item>
		<title>Manejando archivos .INI con PHP</title>
		<link>http://alvlin.com/php/3-manejando-archivos-ini</link>
		<comments>http://alvlin.com/php/3-manejando-archivos-ini#comments</comments>
		<pubDate>Tue, 01 Apr 2008 00:44:10 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://localhost/?p=3</guid>
		<description><![CDATA[Los archivos INI son archivos de texto plano, con una estructura bastante simple. Son fáciles de manejar, y PHP brinda una función para cargar los datos de un archivo ini de forma sencilla.]]></description>
			<content:encoded><![CDATA[<h2>¿Qué es un archivo .INI?</h2>
<p>Se puede leer una <a href="http://es.wikipedia.org/wiki/.ini">descripción del formato INI</a> en la Wikipedia.</p>
<p>Puesto de forma sencilla, un archivo INI es un archivo de texto con un formato bastante simple: cada línea tiene una forma</p>
<p><strong>campo = &#034;valor&#034;</strong></p>
<p>con posibilidad de declarar secciones, declarándolas como <strong>[nombre_sección]</strong>. Son archivos bastante simples y pueden llegar a ser útiles, aunque no sean demasiado flexibles.</p>
<p>Un ejemplo de archivo INI es el archivo de configuración de la base de datos para <a href="http://framework.zend.com/">Zend Framework</a>:<br />
<code>[base_de_datos]<br />
db.adapter = PDO_MYSQL<br />
db.config.host = servidor<br />
db.config.username = usuario<br />
db.config.password = contraseña<br />
db.config.dbname = base</code></p>
<h2>¿Cómo leer un archivo INI?</h2>
<p>Los archivos INI pueden ser transformados en matrices de PHP usando la función <a href="http://www.php.net/parse_ini_file">parse_ini_file</a>.</p>
<p>Esta función admite 2 parámetros: El primero es el nombre del archivo a procesar, y el segundo, opcional, indica si se deben procesar las secciones del archivo.</p>
<p>Por defecto las secciones no se procesan. La diferencia entre ambas formas es que si se procesan las secciones se genera una matriz multidimensional, una matriz para cada sección.</p>
<p>Por ejemplo, aplicar la función al archivo de configuración mostrado antes:</p>
<p><code>var_dump(parse_ini_file('archivo.ini'));</code></p>
<p>Produce la siguiente salida:</p>
<p><code>array(5) {<br />
    ["db.adapter"]=><br />
        string(9) &#034;PDO_MYSQL&#034;<br />
    ["db.config.host"]=><br />
        string(9) &#034;servidor&#034;<br />
    ["db.config.username"]=><br />
        string(4) &#034;usuario&#034;<br />
    ["db.config.password"]=><br />
        string(0) &#034;contraseña&#034;<br />
    ["db.config.dbname"]=><br />
        string(6) &#034;base&#034;<br />
    }</code></p>
<p>Mientras que aplicar la función indicando que deben procesarse las secciones:</p>
<p><code>var_dump(parse_ini_file('archivo.ini', true));</code></p>
<p>Devuelve lo siguiente:</p>
<p><code>array(1) {<br />
    ["base_de_datos"]=><br />
        array(5) {<br />
            ["db.adapter"]=><br />
                string(9) &#034;PDO_MYSQL&#034;<br />
            ["db.config.host"]=><br />
                string(9) &#034;localhost&#034;<br />
            ["db.config.username"]=><br />
                string(4) &#034;root&#034;<br />
            ["db.config.password"]=><br />
                string(0) &#034;&#034;<br />
            ["db.config.dbname"]=><br />
                string(6) &#034;alvlin&#034;<br />
        }<br />
    }</code></p>
<h2>¿Cómo escribir un archivo INI?</h2>
<p>PHP no tiene integrada una función para realizar el proceso inverso, es decir, convertir una matriz en un archivo INI. Es extraño, porque en realidad es un proceso muy simple, si se hace uso de <strong><em>foreach</em></strong>.</p>
<p>Este fragmento de código es todo lo que se necesita para generar el archivo:</p>
<p><code>$salida = '';<br />
foreach($matriz as $clave => $valor)<br />
    $salida .= $clave.' = "'.$valor.'"'.SALTO; </code></p>
<p>Para cada uno de los elementos de la matriz, se escribe la clave, un signo de igualdad (&#034;=&#034;) y el valor entre comillas.</p>
<p>No es necesario que el valor vaya entre comillas, pero &#034;no molesta&#034; y además sí es necesario si el valor tendrá más de una línea. La constante <strong>SALTO</strong> guarda el valor correcto para el salto de línea (&#034;\n&#034; o &#034;\r\n&#034;).</p>
<p>Para escribir las diferentes secciones, se asume que se trata con una matriz multidimensional. Entonces, simplemente se recorre la primera matriz, y para cada uno de sus elementos:</p>
<ol>
<li>Se escribe la clave entre []</li>
<li>Se recorre la matriz que contiene, con el mismo código anterior</li>
<li>Se escribe un salto de línea más. No estoy seguro de que sea necesario para separar secciones, pero sí que resulta en un archivo más prolijo y legible.</li>
</ol>
<p><code>$salida = '';<br />
foreach($matriz as $clave => $matriz_interior) {<br />
    $salida .= '['.$clave.']&#039;.SALTO;</p>
<p>    foreach($matriz_interior as $clave2 => $valor)<br />
        $salida .= $clave2.&#039; = &#034;&#039;.$valor.&#039;&#034;&#039;.SALTO;</p>
<p>    $salida .= SALTO;<br />
}</code></p>
<p>Finalmente, solo queda encargarse de cómo se abrirá el archivo y se guardarán los datos.</p>
<p>En mi función <strong>escribe_ini</strong>, si se pasa una matriz unidimensional para guardar, la misma se copia en otra, de forma de trabajar siempre con una matriz multidimensional. Creo que es la mejor manera de no repetir código.</p>
<p><code class="prettyprint"><br />
function escribe_ini($matriz, $archivo, $multi_secciones = true, $modo = 'w') {<br />
    $salida = '';</p>
<p>    # saltos de línea (usar "\r\n" para Windows)<br />
    define('SALTO', "\n");</p>
<p>    if (!is_array(current($matriz))) {<br />
        $tmp = $matriz;<br />
        $matriz['tmp'] = $tmp;<br />
        unset($tmp);<br />
    }</p>
<p>    foreach($matriz as $clave => $matriz_interior) {</p>
<p>        if ($multi_secciones)<br />
            $salida .= &#039;['.$clave.']&#039;.SALTO;</p>
<p>        foreach($matriz_interior as $clave2 => $valor)<br />
            $salida .= $clave2.&#039; = &#034;&#039;.$valor.&#039;&#034;&#039;.$SALTO;</p>
<p>        if ($multi_secciones)<br />
            $salida .= SALTO;<br />
    }</p>
<p>    $puntero_archivo = @fopen($archivo, $modo);</p>
<p>    if ($puntero_archivo !== false) {<br />
        $escribo = @fwrite($puntero_archivo, $ini);</p>
<p>        if ($escribo === false)<br />
            $devolver = -2;</p>
<p>        else<br />
            $devolver = $escribo;<br />
    }</p>
<p>    else<br />
        $devolver = -1;</p>
<p>    return $devolver;<br />
}</code></p>
<p>Los parámetros que recibe son:</p>
<ol>
<li><var>$matriz</var> - La matriz que se escribirá en el archivo</li>
<li><var>$archivo</var> - La ruta al archivo que se escribirá / creará</li>
<li><var>$multi_secciones</var> - Indica si se deben crear secciones o no.</li>
<li><var>$modo</var> - Se pasa directamente a <strong>fopen()</strong>, indica cómo se abre el archivo.</li>
</ol>
<p>Y los valores de retorno:</p>
<ul>
<li><strong>-1</strong>: Error al abrir el archivo para escritura. El motivo más frecuente es que el usuario no tiene permisos para escribir en el directorio.</li>
<li><strong>-2</strong>: Error al escribir en el archivo.</li>
<li><strong>otro valor</strong>: el número de bytes escrito por <a href="http://www.php.net/fwrite">fwrite()</a></li>
</ul>
<h4 class="relacionados">Enlaces relacionados</h4>
<ul>
<li><a href="http://es.wikipedia.org/wiki/.ini">Wikipedia: .ini</a></li>
<li><a href="http://www.php.net/parse_ini_file">Manual de PHP: parse_ini_file</a></li>
<li><a href="http://www.php.net/manual/es/ref.filesystem.php">Manual de PHP: funciones del sistema de archivos</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/php/3-manejando-archivos-ini/feed</wfw:commentRss>
		</item>
		<item>
		<title>Nuevo español: ¿tanto más da una letra que otra?</title>
		<link>http://alvlin.com/baul/37-nuevo-espanol-%c2%bftanto-mas-da-una-letra-que-otra</link>
		<comments>http://alvlin.com/baul/37-nuevo-espanol-%c2%bftanto-mas-da-una-letra-que-otra#comments</comments>
		<pubDate>Wed, 16 Jan 2008 23:12:08 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Baúl]]></category>

		<guid isPermaLink="false">http://alvlin.blogcreativo.com/2008/01/16/nuevo-espanol-%c2%bftanto-mas-da-una-letra-que-otra/</guid>
		<description><![CDATA[Aparecido allá por el 2001 en el diario El País, de Uruguay.
 Autor: Arturo Pérez Reverte

Un artículo sobre la ortografía española, y lo feo que quedaría el idioma si se aplicaran ciertas "simplificaciones" que de vez en cuando se proponen...]]></description>
			<content:encoded><![CDATA[<p>Aparecido allá por el 2001 en el diario El País, de Uruguay.<br />
 Autor: Arturo Pérez Reverte</p>
<p>Un artículo sobre la ortografía española, y lo feo que quedaría el idioma si se aplicaran ciertas &#034;simplificaciones&#034; que de vez en cuando se proponen&#8230;<br />
&#8212;&#8212;&#8212;-</p>
<p>Acabo de recibir un e-mail de Pepe Perona, el maestro de gramática, reproduciendo otro que le ha enviado no sabe quién. Desconocemos el nombre del autor original; así que, en esta versión postmoderna del manuscrito encontrado, me limito a seguir el juego iniciado por mano genial y anónima. El maravilloso texto se refiere a una supuesta reforma ortográfica que va a aplicar la Real Academia, a fin de hacer más asequible el español como lengua universal de los hispanohablantes y de las soberanías soberanistas. Y lo reproduzco con escasas modificaciones</p>
<p>Según el plan de los señores académicos -expertos en lanzada a moro muerto-, la reforma se llevará a cabo empezando por la supresión de las diferencias entre c, q y k. Komo komienzo, todo sonido parecido al de la k será asumido por esa letra. En adelante se eskribirá kasa, keso, Kijote. También se simplificará el sonido de la c y la z para igualarnos a nuestros hermanos hispanoamericanos: &#034;El sapato de Sesilia es asul&#034;. Y desapareserá la doble c, reemplasándola la x: &#034;mi koche tuvo un axidente&#034;. Grasias a esta modifikasión los españoles no tendrán ventajas ortográfikas frente a los hermanos hispanoparlantes por su estraña pronunsiasión de siertas letras.</p>
<p>Se funde la b con la v, ya ke no existe diferensia entre el sonido de la b larga y la v chikita. Por lo kual desapareserá la v y beremos kómo obbiamente basta kon la b para ke bibamos felises y kontentos. Lo mismo pasará kon la elle y la ye. Todo se eskribirá kon y: &#034;Yébame de biaje a Sebiya, donde la yubia es una marabiya&#034;. Esta integrasión probokará agradesimiento general de kienes hablan kasteyano, desde Balensia hasta Bolibia.</p>
<p>La hache, kuya presensia es fantasma en nuestra lengua, kedará suprimida por kompleto: así, ablaremos de abichuelas o alkool. Se akabarán esas komplikadas y umiyantes distinsiones entre echo y hecho, y no tendremos ke rompernos la kabesa pensando kómo se eskribe sanaoria. Así ya no abrá ke desperdisiar más oras de estudio en semejante kuestión ke nos tenía artos.</p>
<p>Para mayor konsistensia, todo sonido de erre se eskribirá kon doble r: &#034;El rrufián de Rroberto me rregaló una rradio&#034;. Asimismo, para ebitar otros problemas ortográficos, se fusionan la g y la j, para ke así jitano se eskriba komo jirafa y jeranio komo jefe. Aora todo ba kon jota de cojer. Por ejemplo: &#034;El jeneral korrijió los korreajes&#034;. No hay duda de ke estas sensiyas modifikasiones arán ke ablemos y eskribamos todos kon jenial rregularidad y más rrápido rritmo.</p>
<p>Orrible kalamidad del kasteyano, jeneralmente, son las tildes o asentos. Esta sankadiya kotidiana desaparese kon la rreforma; aremos komo el ingles, ke a triunfado unibersalmente sin tildes. Kedaran eyas kanseladas en el akto, y abran de ser el sentido komun y la intelijensia kayejera los ke digan a ke se rrefiere kada bokablo: &#034;Obserba komo komo la paeya&#034;.</p>
<p>Las konsonantes st, ps, bs o pt juntas kedaran komo simples t o s, kon el fin de aprosimarnos a la pronunsiasion ispanoamerikana y para mejorar ete etado konfuso de la lengua. También seran proibidas siertas konsonantes finales ke inkomodan y poko ayudan al siudadano: &#034;¿Ke ora da tu rrelo?&#034;, &#034;As un ueco en la pare&#034; y &#034;Erneto jetiona lo aorro de Aguti&#034;. Por supueto, entre eyas se suprimiran las eses de los plurales: &#034;La mujere y lo ombre tienen la mima atitude y fakultade inteletuale&#034;.</p>
<p>Yegamo trite e inebitablemente a la eliminasion de la d del partisipio pasao y kanselasion de lo artikulo, impueta por el uso: &#034;E bebio te erbio y kon eso me abio&#034;. Kabibajo asetaremo eta kotumbre bulgar, ya ke el pueblo yano manda, kedando suprimia esa de interbokalika ke la jente no pronunsia. Adema, y konsiderando ke el latin no tenia artikulo y nosotro no debemo inbentar kosa ke Birjilio, Tasito y lo otro autore latino rrechasaba, kateyano karesera de artikulo. Sera poco enrredao en prinsipio, y ablaremo komo fubolita yugolabo en ikatola, pero depue todo etranjero beran ke tarea de aprender nuebo idioma rresultan ma fasile. Profesore terminaran benerando akademiko de la lengua epañola ke an desidio aser reforma klabe para ke nasione ispanoablante gosemo berdaderamente del idioma de Servante y Kebedo.</p>
<p>Eso si: nunka asetaremo ke potensia etranjera token kabeyo de letra eñe. Ata ai podiamo yega. Eñe rrepresenta balore ma elebado de tradision ipanika y primero kaeremo mueto ante ke asetar bejasione a simbolo ke a sio y e korason bibifikante de lengua epañola unibersa.</p>
]]></content:encoded>
			<wfw:commentRss>http://alvlin.com/baul/37-nuevo-espanol-%c2%bftanto-mas-da-una-letra-que-otra/feed</wfw:commentRss>
		</item>
		<item>
		<title>20 formas de arruinar una idea</title>
		<link>http://alvlin.com/baul/36-20-formas-de-arruinar-una-idea</link>
		<comments>http://alvlin.com/baul/36-20-formas-de-arruinar-una-idea#comments</comments>
		<pubDate>Wed, 16 Jan 2008 23:05:41 +0000</pubDate>
		<dc:creator>alvlin</dc:creator>
		
		<category><![CDATA[Baúl]]></category>

		<guid isPermaLink="false">http://alvlin.blogcreativo.com/2008/01/16/20-formas-de-arruinar-una-idea/</guid>
		<description><![CDATA[Otro de esos que circulan hasta el hartazgo por las más diversas páginas de internet. Uno mas para el baúl&#8230;..
Las ideas resultan molestas. ¿Cómo conseguir defenderse de los efectos perturbadores de ellas?
Con estrategia persuasiva y resistencia tenaz. Contamos aquí veinte formas de enterrar una idea, no para destruir la de los otros, sino para defender [...]]]></description>
			<content:encoded><![CDATA[<p>Otro de esos que circulan hasta el hartazgo por las más diversas páginas de internet. Uno mas para el baúl&#8230;..</p>
<p>Las ideas resultan molestas. ¿Cómo conseguir defenderse de los efectos perturbadores de ellas?<br />
Con estrategia persuasiva y resistencia tenaz. Contamos aquí veinte formas de enterrar una idea, no para destruir la de los otros, sino para defender las propias.</p>
<p>He aquí el catálogo destructor:</p>
<ul>
<li>Ignorarla. Poner un silencio de muerte a toda propuesta desanimará a su autor, aunque sea de los más curtidos.</li>
<li>Eludirla. Se presiente la llegada de una idea a la vista del apuro y de la ansiedad del que se prepara a exponerla. Cambiar de tema, levantar la sesión, hacerse el tonto, son modos para evitar que prospere.</li>
<li>Despreciarla. Es muy eficaz levantar una ceja y decir con voz dulce y tono de asombro &#034;no dirás esto en serio&#034;.</li>
<li>Ridiculizarla. Decir riendo &#034;Oh, está muy bien, habrás tenido que velar toda la noche para tener esa idea&#034;. Si, por casualidad, esto es verdad, es aún más gracioso.</li>
<li>Elogiarla. Una avalancha de elogios hará que todos aborrezcan la idea, incluso su autor.</li>
<li>Propagar que no es nueva. Si se consigue dar a la idea un cierto parentesco con otra ya conocida, el hecho de que ésta pueda ser mejor pasará inadvertida.</li>
<li>Hacer ver que no va con la política de la empresa. Como nadie sabe cuál es esa política, no se corre ningún riesgo de ser contradicho.</li>
<li>Hablar de lo que va a costar. Como las ganancias son imaginarias y el costo es inmediato y real, la idea se pondrá en entredicho. Si poner en marcha la idea resulta gratuito, será fácil advertir que lo que no cuesta nada no vale gran cosa.</li>
<li>Decir que ya se ha ensayado antes. Esta ofensiva es particularmente eficaz cuando la idea viene de un novato,