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

<channel>
	<title>Stereonaut! &#187; Search Results  &#187;  columna+de+perl</title>
	<atom:link href="http://stereonaut.net/search/columna+de+perl/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>http://stereonaut.net</link>
	<description>A weblog by David Moreno.</description>
	<lastBuildDate>Tue, 02 Aug 2011 15:57:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Google&#039;s first tweet</title>
		<link>http://stereonaut.net/googles-first-tweet/</link>
		<comments>http://stereonaut.net/googles-first-tweet/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 18:02:34 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[planeta linux]]></category>
		<category><![CDATA[binary]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[octal]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://log.damog.net/?p=836</guid>
		<description><![CDATA[Google created an official Twitter account. Its first tweet was something odd: I&#039;m 01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100 01110101 01100011 01101011 01111001 00001010 I had previously written (in Spanish, for La Columna de Perl), how to quickly decode this &#034;way&#034; of binary writing with Perl&#039;s chr and oct. So, to find [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://google.com">Google</a> created an official <a href="http://twitter.com">Twitter</a> <a href="http://twitter.com/google">account</a>. Its <a href="http://twitter.com/google/status/1251523388">first tweet</a> was something odd:</p>
<blockquote><p><span class="status-body"><span class="entry-content">I&#039;m 01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100 01110101 01100011 01101011 01111001 00001010</span></span></p></blockquote>
<p>I had <a href="http://log.damog.net/2007/10/tip-perl-del-dia-chr-y-oct-en-un-loop-map/">previously written</a> (in Spanish, for <a href="http://log.damog.net/index.php?s=columna+de+perl">La Columna de Perl</a>), how to quickly decode this &#034;way&#034; of binary writing with Perl&#039;s <tt>chr</tt> and <tt>oct</tt>. So, to find out what was Google really tweeting, run:</p>
<blockquote><p>
<code>perl -e 'map { print chr oct "0b".$_; } split /\s/, "01100110 01100101 01100101 01101100 01101001 01101110 01100111 00100000 01101100 01110101 01100011 01101011 01111001 00001010";'</code>
</p></blockquote>
<p>So, what&#039;s really happening with this snippet? Well, the zeroes-ones string is being passed to the <tt>split</tt> function that explodes the string with a whitespace delimiter and passes that exploded string, a list, to <tt>map</tt>. <tt>map</tt> takes each one of the elements, the 8-character substring, one by one and preppends &#034;<tt>0b</tt>&#034; so that <tt>oct</tt> can understand it as an octal string and returns the value for that character. Then, that value is passed to <tt>chr</tt> that takes the numerical representation of a given character and returns that character. Then, it&#039;s just passed to print that, surprise, prints out that value.</p>
<p>How do you do it in your language of choice?</p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/googles-first-tweet/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Tip Perl del día: 0E0</title>
		<link>http://stereonaut.net/tip-perl-del-dia-0e0/</link>
		<comments>http://stereonaut.net/tip-perl-del-dia-0e0/#comments</comments>
		<pubDate>Fri, 19 Oct 2007 00:59:05 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/10/tip-perl-del-dia-0e0/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p>Empezaré escribiendo algunos tipcitos que me voy encontrando a mi paso al cabalgar sobre el felpudo lomo del dromedario de Perl durante mi camino por la vida. Las Columnas.pl, tips y otras cosas perlosas podrán revisarse en la categoría &#039;perl&#039; de este blog.</p>
<p>Estoy trabajando con algunos contadores. Tengo que agregar un nuevo contador por hora e ir sumando el contador principal durante la hora actual, sin mucho problema, ¿no? Sin embargo, si la hora actual no existe en la base de datos, tengo que crear un nuevo registro. Debido a mi pésima capacidad bajo cualquier cosa que contenga las siglas SQL, tuve que platicar con alguien más para que diera una idea simple y clara de qué hacer.</p>
<p>Intento sumar el contador dada la hora actual, pero si no afectó a ninguna fila, entonces creo la fila. Ese concepto es mucho mejor que hacer un count(*) primero, validar si existe la fila, crearla si no, actualizarla si sí. Para verificar si mi primer query (el &#034;UPDATE&#034;) afectó a alguna columna, podemos usar el método do() que provee DBI y que hereda tu DBD favorito, en mi caso, pues no tengo otra alternativa y a final de cuentas me termina valiendo un pepino por el momento, uso DBD::mysql.</p>
<p>do() regresa, en contexto escalar, el número de filas afectadas por el query que se le haya pasado. Sin embargo, y aquí viene lo interesante y el tip del día, utiliza un valor llamado &#034;0E0&#034;, una cadena. Si fueron afectadas, digamos, 3 filas por el query, do() regresará ese número, pero si no fue afectada ninguna fila, es decir, cero filas, regresa el valor &#034;0E0&#034;, que es básicamente &#034;cero, pero cierto&#034;.</p>
<p>Como bien se sabe (y si no sabes, deberías saber), valores como cadenas vacías o ceros, se evalúan como falsas en las operaciones binarias en Perl. Sin embargo, &#034;0E0&#034; se traduce a cero, pero con un valor verdadero, lo cual es muy útil para muchos otros casos en los que obtener un cero podamos usar como valor verdadero.</p>
<p>En mi ejemplo, usé:</p>
<p>my $aff_rows = $sth-&gt;do($query);<br/><br />
if($arr_rows == 0) { # Este bloque se ejecuta }</p>
<p><br/><br />
Que es diferente a usar:</p>
<p>my $aff_rows = $sth-&gt;do($query);<br/><br />
if(!$arr_rows){ # Este bloque no }</p>
<p><br/><br />
El if evalúa si el valor de $arr_rows es cero, que en muchos casos sería validar si es cierto o falso, pero como $aff_rows es en realidad &#034;cero pero cierto&#034;, entonces la condición resulta verdadera. En el segundo if, se valida si el valor de $arr_rows no es verdadero, que en casos comunes sería lo mismo que el primer if, pero la validación resulta falsa y no se ejecuta el bloque. Chido, ¿no? <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/tip-perl-del-dia-0e0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatización en web con WWW::Mechanize</title>
		<link>http://stereonaut.net/automatizacion-en-web-con-wwwmechanize/</link>
		<comments>http://stereonaut.net/automatizacion-en-web-con-wwwmechanize/#comments</comments>
		<pubDate>Thu, 06 Sep 2007 02:16:25 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/09/automatizacion-en-web-con-wwwmechanize/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><a title="__index__" name="__index__" id="__index__"></a>
<ul>
<li>
<a href="#la_columna_pl__4">La Columna.pl #4</a></p>
<ul>
<li>
<a href="#automatizaci%EF%BF%BD_n_en_web_con_www__mechanize">Automatización en web con WWW::Mechanize</a></p>
<ul>
<li><a href="#introducci%EF%BF%BD_n">Introducción</a></li>
<li><a href="#script">Script</a></li>
<li><a href="#fin">Fin</a></li>
<li><a href="#referencias_%EF%BF%BD_tiles">Referencias Útiles</a></li>
</ul>
</li>
<li><a href="#autor">Autor</a></li>
<li><a href="#licencia_de_uso">Licencia de uso</a></li>
</ul>
</li>
<li><a href="#sobre_la_columna_pl">Sobre <em>La Columna.pl</em></a></li>
</ul>
<hr />
<h1>
<a title="la_columna_pl__4" name="la_columna_pl__4" id="la_columna_pl__4"></a>La Columna.pl #4</h1>
<h2>
<a title="automatizaci�_n_en_web_con_www__mechanize" name="automatizaci%EF%BF%BD_n_en_web_con_www__mechanize" id="automatizaci�_n_en_web_con_www__mechanize"></a>Automatización en web con WWW::Mechanize</h2>
<h3>
<a title="introducci�_n" name="introducci%EF%BF%BD_n" id="introducci�_n"></a>Introducción</h3>
<p><code>WWW::Mechanize</code>
<p> es un módulo muy interesante. Básicamente nos permite automatizar o mecanizar una conversación a través de una página web. Es decir, poder automatizar el procesamiento de enlaces, imágenes, formas, etc. En realidad <code>WWW::Mechanize</code> actúa como una subclase de <code>LWP::UserAgent</code>, que es el mítico LWP en Perl.</p>
<p>Hay que entender que todo lo que hacemos en un navegador web, o casi todo, es posible automatizarlo por medio de scripts, debido a que lo que en realidad sucede es que trabajamos con cabeceras y cuerpo <code>HTTP</code>, tanto en petición como en respuesta. Todo es a través del protocolo <code>HTTP</code>.</p>
<p>Mi trabajo actual requiere mucha interacción automatizada con páginas web y <code>WWW::Mechanize</code> me ha permitido hacer desarrollos muchos más rápidos, mucho mejor encapsulados y con un nivel de abstracción menor.</p>
<p>En esta cuarta columna, quiero hacer algo para mostrar de qué es capaz <code>WWW::Mechanize</code> y que ustedes, amables lectores, vean su utilidad real. Lo que haré será un proceso de autenticación en el wiki del proyecto Debian y la obtención de una de sus páginas. Básicamente es loguearme en el wiki y obtener el valor de uno de los campos de una forma. Lo interesante en este asunto viene al automatizar el login en un sistema basado en web, escribir en una forma y enviar forma, obtener campos, etc: <code>WWW::Mechanize</code> lo hace muy simple.</p>
<p>Manos a la obra.
</p>
<h3>
<a title="script" name="script" id="script"></a>Script</h3>
<p>
Vamos a empezar por invocar a nuestro intérprete de Perl activando warnings, así como el pragma <code>strict</code>.
</p>
<pre>
 #!/usr/bin/perl -w

 use strict;</pre>
<p>
Como necesitaremos un nombre de usuario y contraseña para acceder el wiki en Debian (es necesario para editar páginas), vamos a tomarlos como argumentos:
</p>
<pre>
 my $username = $ARGV[0] || die "ERR: Es necesario especificar un nombre de usuario", "\n";

 my $password = $ARGV[1] || die "ERR: Es necesario especificiar una contraseña", "\n";</pre>
<p>
Los argumentos vienen en el arreglo <code>@ARGV</code>: El primer argumento de nuestro programa será el nombre de usuario y el segundo será la contraseña. Si no existen, entonces nuestro programa morirá.</p>
<p>A continuación llamamos al módulo <code>WWW::Mechanize</code> y creamos un objeto de ese tipo.
</p>
<pre>
 use WWW::Mechanize;

 my $mech = WWW::Mechanize-&gt;new;</pre>
<p>
Bastante simple.</p>
<p>Ahora tenemos que ver qué es lo que haríamos desde un navegador convencional para hacer lo que queremos. Lo más lógico es que entráramos a la página del wiki de Debian, cuya URL es <a href="http://wiki.debian.org/"><a href="http://wiki.debian.org/">http://wiki.debian.org/</a></a>. Vamos a hacerlo de la misma manera en el script.
</p>
<pre>
 $mech-&gt;get('<a href="http://wiki.debian.org/"><a href="http://wiki.debian.org/">http://wiki.debian.org/</a></a>');

 unless($mech-&gt;success) {

  die "Tuvimos problemas al acceder la página de Debian", "\n";

 }</pre>
<p>
Básicamente estamos utilizando dos métodos disponibles en Mechanize: <code>get()</code> y <code>success()</code>. El primero hará que nuestro objeto viaje hasta la página que le indiquemos. En cualquier caso, el método <code>success()</code> nos indica por medio de un valor booleano si la última operación que se realizó en Mechanize, fue exitosa o algo falló, lo cual nos sirve para tener más control del flujo de nuestra aplicación. Si no tenemos problemas con <code>get()</code>, entonces el programa no morirá con el mensaje especificado; sin embargo si sí hubo problema, es decir, <code>success()</code> regresa falso, entonces entrará en acción el <code>die()</code>. Continuemos.</p>
<p>Una vez que estamos en Firefox (u Opera, o Internet Explorer, no sé) en la página <a href="http://wiki.debian.org/,"><a href="http://wiki.debian.org/,">http://wiki.debian.org/,</a></a> ¿qué es lo siguiente? Bueno, lo normal, que es al no estar logueados, nos aparezca un link que dice &#034;Login&#034;. En un proceso común tendríamos que dar clic en él para continuar con el proceso de autenticación. Eso mismo haremos:
</p>
<pre>
 $mech-&gt;follow_link(text =&gt; 'Login') or die "ERR: No pude dar clic en login", "\n";</pre>
<p>
Así de simple. Con el método <code>follow_link()</code> y el parámetro &#039;text&#039;, podemos indicarle a Mechanize que donde estamos actualmente, que sería la página frontal del wiki, siga el enlace cuyo texto es &#039;Login&#039;. Mechanize nos permite incluso acomodar regex en estos campos, lo cual nos facilitaría aún más al lidiar con contenido dinámico o situaciones más complejas. Como <code>follow_link()</code> regresa realmente un objeto <code>HTTP::Response</code> en caso de éxito, también provee un retorno en caso de falla, que es <code>undef</code>. Así que si hubo una falla al intentar seguir el enlace, moriremos con el mensaje de error especificado.</p>
<p>Una vez que dimos clic en &#039;Login&#039;, podemos ver en nuestro navegador convencional que la página donde nos encontramos es aquella con la URL &#039;<a href="http://wiki.debian.org/UserPreferences"><a href="http://wiki.debian.org/UserPreferences">http://wiki.debian.org/UserPreferences</a></a>&#039;. En realidad pudimos habernos evitado algo de código al empezar nuestro primer <code>get()</code> con esta URL pero intentaba mostrar un poco de las bondades de Mechanize. ¿Qué tal si en tu script no sabes en qué URL se encuentra tu navegador de Mechanize? Puedes usar el método <code>uri()</code> e incluso el método <code>response()</code>. Eso te ayudará a analizar bien el flujo de tu programa.</p>
<p>En fin, en esa página de UserPreferences podemos ver que tenemos una forma para introducir &#034;Name&#034;, &#034;Password&#034;, etc. En realidad esos dos campos son los que realmente nos interesan. Para ésto, nos puede servir mucho la extensión WebDeveloper de Firefox, pues con ella podemos ver la información detallada de las formas en las páginas. Lo que queremos saber es cuál es nombre de la forma para ingresar el nombre de usuario y la contraseña, y además, el nombre de estos dos campos (hay que recordar que comúnmente las formas en HTML llevan un parámetro &#034;name&#034;). O incluso puedes intentar buscar estos parámetros viendo el código HTML directo desde la página.</p>
<p>Luego de ver el HTML (o de usar la extensión de Firefox) nos damos cuenta que en la página de autenticación de Debian hay tres formas, sin embargo, la forma donde se introducen el nombre de usuario y la contraseña, ¡no tiene nombre! Mechanize sabe que algunos webmasters no colocan esta información, así que provee otra forma en que puedes usar esas formas: Por número. Puedes especificar si trabajarás con la primera, segunda, tercera o enésima forma. En nuestro ejemplo, la forma de autenticación es la tercera:
</p>
<pre> eval {

  $mech-&gt;form(3);

  $mech-&gt;submit_form('username' =&gt; $username, 'password' =&gt; $password);

 };</pre>
<pre>
 die "ERR: Problemas al enviar la forma: $@", "\n" if $@;</pre>
<p>
Un bonito pedazo de código aquí. Lo primero que notamos es que usamos un bloque <code>eval{}</code> para encapsular dos métodos, <code>form()</code> y <code>submit_form()</code>. <code>form()</code> selecciona la forma con la que trabajaremos, en este caso la tercera y <code>submit_form()</code> envía esa forma con los campos indicados. Es bastante intuitivo, ¿no crees? Y ya, básicamente eso es lo único que necesitamos para autenticarnos. En caso de falla con <code>submit_form()</code>, la aplicación muere, sin embargo, eso lo intentamos evitar usando <code>eval{}</code>. Si algo dentro del bloque de eval fallara y muriera, <code>eval{}</code> llena una variable especial, <code>$@</code> con el mensaje de error y ya después nosotros podemos morir o hacer lo que queramos. Bonito, ¿no es así?</p>
<p>Una vez que mandamos la forma, tenemos que asegurarnos que no nos haya mandado mensaje de password erróneo o algo así. Una cosa es que el envío de la forma con sus parámetros sea exitoso o no, y otra diferente que la información de usuario y contraseña sean incorrectos. ¿Cómo saber lo que necesitamos para identificar ésto? Podemos intentar en nuestro Firefox poniendo información errónea en estos campos e intentar loguearse. Al hacer pruebas de este tipo veo que es diferente si el usuario no existe o si la contraseña es errónea.</p>
<p>Si el usuario no existe, la página nos manda un error que dice: &#034;Unknown user name: &#034;sdfsdfsdf&#034;. Please enter user name and password.&#034;. Si la contraseña está mal (o sea, el usuario existe, pero la contraseña es errónea), la página despliega: &#034;Sorry, wrong password.&#034;. Vamos a ver cómo controlaríamos dichos mensajes:
</p>
<pre>
 die "Unknown user name!", "\n" if $mech-&gt;content =~ /Unknown user name/;

 die "Wrong password!", "\n" if $mech-&gt;content =~ /Sorry, wrong password/;</pre>
<p>
¡Qué sencillo! Morimos en caso de que el método <code>content()</code>, que nos regresa la cadena con todo el HTML de la página actual, contiene alguna de ambas cadenas. Código simple para regexs simples. Si no tenemos ninguno de ambos, asumimos que estaremos ya bien logueados.</p>
<p>Ahora, ¿qué es lo que queremos hacer? Digamos que queremos obtener lo que nuestra propia página tiene escrito. Las páginas de los usuarios son simples páginas del wiki con nuestro nombre de usuario, en mi caso, &#034;http://wiki.debian.org/DavidMorenoGarza&#034;, o lo que es lo mismo &#034;<code><a href="http://wiki.debian.org/%24username">http://wiki.debian.org/$username</a></code>&#034;:
</p>
<pre>
 $mech-&gt;get("<a href="http://wiki.debian.org/"><a href="http://wiki.debian.org/">http://wiki.debian.org/</a></a>$username");</pre>
<p>
Estando en dicha página hay en enlace que dice &#034;Edit&#034;, ese es en el que tendríamos que dar clic para entrar a la forma directa de nuestra página:
</p>
<pre>
 $mech-&gt;follow_link(text =&gt; 'Edit');</pre>
<p>
Y una vez en la página de edición, nos encontramos con una forma nuevamente, que es básicamente la caja de edición de la página. Al leer el HTML o usando WebDeveloper, nos encontramos con que la forma sí tiene nombre y la caja con el texto de la página se encuentra en un campo llamado &#034;editor-textarea&#034;. Pues vamos a obtener ese texto:
</p>
<pre>
 $mech-&gt;form_name('editor');

 my $pagetext = $mech-&gt;value("editor-textarea");</pre>
<p>
Con eso seleccionamos la forma cuyo nombre es &#034;editor&#034; y con <code>value()</code>, seleccionamos el valor de &#034;editor-textarea&#034; y lo guardamos en la variable $pagetext.</p>
<p>¿Qué más podemos hacer? Lo que queramos, quizás queremos usar ese valor y escribirlo en un archivo, modificarlo y volverlo a guardar, obtener el preview luego de modificarlo, etc, etc. En realidad desde aquí la imaginación es el límite.
</p>
<h3>
<a title="fin" name="fin" id="fin"></a>Fin</h3>
<p>
Una regla de oro que he aprendido luego de usar mucho WWW::Mechanize es que casi todo lo que puedas hacer en un navegador convencional, lo puedes hacer también con este módulo. No, no puedes interpretar JavaScript, pero muchas veces no lo necesitas si saber leer bien el HTML de una página y entiendes lo que estás realmente haciendo. A final de cuentas si entiendes perfectamente lo que pasa en una conversación por HTTP quizás ni siquiera necesites Mechanize, pues como un amigo me comentaba, Mechanize es simplemente una rompecabezas armado de muchos módulos alrededor de LWP.</p>
<p>Hazme llegar tus preguntas o comentarios a mi correo, <code>damog@espiral.org.mx</code>. Estaré encantado de saber qué usos le das a Mechanize.
</p>
<h3>
<a title="referencias_�_tiles" name="referencias_%EF%BF%BD_tiles" id="referencias_�_tiles"></a>Referencias Útiles</h3>
<ul>
<li><a href="http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize.pm"><a href="http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize.pm">http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize.pm</a></a></li>
<li><a href="http://search.cpan.org/~gaas/libwww-perl-5.808/lib/LWP/UserAgent.pm"><a href="http://search.cpan.org/~gaas/libwww-perl-5.808/lib/LWP/UserAgent.pm">http://search.cpan.org/~gaas/libwww-perl-5.808/lib/LWP/UserAgent.pm</a></a></li>
<li><a href="http://wiki.debian.org/"><a href="http://wiki.debian.org/">http://wiki.debian.org/</a></a></li>
<li><a href="http://wiki.debian.org/UserPreferences"><a href="http://wiki.debian.org/UserPreferences">http://wiki.debian.org/UserPreferences</a></a></li>
<li><a href="http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize/Examples.pod"><a href="http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize/Examples.pod">http://search.cpan.org/~petdance/WWW-Mechanize-1.30/lib/WWW/Mechanize/Examples.pod</a></a></li>
</ul>
<h2>
<a title="autor" name="autor" id="autor"></a>Autor</h2>
<p>
Durante el día, David Moreno Garza (<a href="http://www.damog.net/"><a href="http://www.damog.net/">http://www.damog.net/</a></a>) desarrolla aplicaciones, sistemas y proyectos para una incipiente empresa norteamericana;; adicionalmente es consultor independiente en empresas mexicanas y extranjeras utilizando Perl. Durante la noche intenta salvar al mundo del mal usando expresiones regulares y <em>netiquette</em>.
</p>
<h2>
<a title="licencia_de_uso" name="licencia_de_uso" id="licencia_de_uso"></a>Licencia de uso</h2>
<p>
Copyright © 2007 David Moreno Garza.</p>
<p>This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <a href="http://www.opencontent.org/openpub/"><a href="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</a></a>).</p>
<hr />
<h1>
<a title="sobre_la_columna_pl" name="sobre_la_columna_pl" id="sobre_la_columna_pl"></a>Sobre <em>La Columna.pl</em><br />
</h1>
<p><em>La Columna.pl</em>
<p> es una columna quincenal que escribe el autor alrededor de Perl. Está inspirada en las columnas que Randal L. Schwartz ha escrito desde hace varios años. Por medio de recetas, consejos, instructivos y guías, el autor pretende propiciar interés en la gente para que conozca un poco más a fondo este apasionante lenguaje de programación y así fomentar una comunidad más sólida alrededor de él.</p>
<p>Visite <a href="http://www.damog.net/la-columnapl"><a href="http://www.damog.net/la-columnapl">http://www.damog.net/la-columnapl</a></a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/automatizacion-en-web-con-wwwmechanize/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Redirecciones</title>
		<link>http://stereonaut.net/redirecciones/</link>
		<comments>http://stereonaut.net/redirecciones/#comments</comments>
		<pubDate>Sat, 01 Sep 2007 03:48:10 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/08/redirecciones/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<h1>La Columna.pl #3</h1>
<h2>
<a title="redirecciones" name="redirecciones" id="redirecciones"></a>Redirecciones</h2>
<p>
Bueno, el ofrecer disculpas por tardanzas tan prolongadas en la entrega de esta columna, ya se está haciendo costumbre, ¡y apenas van tres columnas! Por ahora mejor tomaré otro <em>approach</em> para las próximas liberaciones de la misma: Se harán nuevas entregas cuando estén listas. Un enfoque plenamente debianero.</p>
<p>Como sea, durante el mes pasado estuve principalmente preparándome, asistiendo y recuperándome de la Debian Conference que se llevó a cabo en las tierras del whisky, Escocia (pueden ver fotografías en mi galería). Como éste era un viaje que había planeado con mucha antelación, cuando supe que el <code>YAPC::NA</code> se realizaría en Houston, no pude dejar de lamentarme semanas y semanas por que estaría destinado a no asistir. En fin, a ver qué tal el próximo año. Gracias a las personas que preguntaron sobre el paradero de ésta, su columna de confianza.</p>
<p>En fin.</p>
<p>En los últimos días estuve revisando un sitio que implementaba cosas interesantes. Entre ellas, una aplicación que hacía redirecciones en web. Éstas son algo populares, pero no muy conocidos: Una aplicacioncita web que nos permite crear URLs del tipo: <code><a href="http://www.midominio.com/cgi-bin/forward.cgi?url=damog.net">http://www.midominio.com/cgi-bin/forward.cgi?url=damog.net</a></code>. Básicamente, es un CGI que recibe un argumento y hace una redirección hacia ese sitio, ¿muy simple? Quizás sí, pero nosotros podemos agregarle mucha más funcionalidad muy interesante. Es cierto que dichas redirecciones pueden hacerse con <code>mod_rewrite</code> de Apache o similares, pero obviamente no le podemos agregar tanta flexibilidad y triques como con un script en Perl.</p>
<p>Lo que quiero, entonces, es un redireccionador que en primer lugar, verifique que la URL sea válida, quizá escribir en un log o una base de datos y haga la redirección. Además, utilizaremos un poco de rewrites para añadirle un poco de atractivo visual al asunto.</p>
<p>Empezaré a escribir el <code>redir.cgi</code>:
</p>
<pre> #!/usr/bin/perl

use strict;
use warnings;

use CGI qw(:standard);
use Data::Validate::URI qw(is_http_uri is_https_uri);

my $url = param('url') || '<a href="http://www.damog.net//"><a href="http://www.damog.net/">http://www.damog.net/</a></a>‘;
$url =~ s/^http(s?)://http$1:///;

&amp;wrong($url) unless is_http_uri($url) || is_https_uri($url);

# Más código…
# Quizás escribir a un log, etc..
print “Location: $url”, “\n\n”;

sub wrong {
my ($url) = shift;
print “Content-Type: text/plain”, “\n\n”;
print “It looks like $url is not a valid URL!”;
exit;
}</pre>
<p>
Es un código bastante corto y simple. Usamos un par de pragmas, un par de módulos, procesamos el parámetro que recibiremos, validamos y redireccionamos. Vamos por partes. Para poder realizar este ejemplo, necesitaremos tener habilitada la ejecución de CGIs en nuestro servidor web. Para más información al respecto, puedes revisar la información de Apache o Cherokee al respecto, la explicación de tal procedimiento está fuera de contexto en esta columna. Encuentra enlaces útiles más abajo, en la sección de <em>Referencias útiles</em>.
</p>
<pre> #!/usr/bin/perl

use strict;
use warnings;</pre>
<p>
Desde luego, nuestro CGI necesitará saber dónde encontrar el intérprete para la ejecución. Además, como buena práctica de programación, añadiremos los pragmas <code>strict</code> y <code>warnings</code>. Desde un personal punto de vista, una vez que nuestra aplicación en desarrollo haya quedado limpia de errores fatales o advertencias, podríamos deshabilitar ambos pragmas, los cuales podrían volverse a cargar cuando se haga <em>debugging</em> o algo similar; pero a final de cuentas es sólo un punto de vista personal que cada quién seguirá teniendo sus propias razones y necesidades.
</p>
<pre> use CGI qw(:standard);
use Data::Validate::URI qw (is_http_uri is_https_uri);</pre>
<p>
Utilizamos dos módulos. El primero es un módulo que pertenece a Perl y que nos permite un manejo muy sencillo de, claro, CGIs y todo alrededor de ellos. Nosotros realmente lo utilizamos para obtener el parámetro que se le mande al script, con la función <code>param()</code>, que de hecho puede recibir los parámetros tanto en HTTP GET o POST. También podríamos obtener dicho parámetro desde el hash <code>%ENV</code>, pero hay que hacer un poco más de talacha, así que mejor usaremos <code>CGI.pm</code> y listo.</p>
<p><code>Data::Validate::URI</code> es un módulo que encontré en CPAN que hace mínimamente lo que necesitamos, validar URIs. Si una cadena es una URI de HTTP o HTTPS, se valida y regresará falso en dado que no lo sea. Eso es más que suficiente. La explicación sobre la instalación de módulos de CPAN queda fuera del contexto de esta columna.
</p>
<pre> my $url = param('url') || '<a href="http://www.damog.net//"><a href="http://www.damog.net/">http://www.damog.net/</a></a>‘;
$url =~ s/^http(s?):/{1,2}/http$1:///g;</pre>
<p>
Creamos la variable <code>$url</code> con el parámetro GET o POST que nos traen al CGI. En caso de que no exista dicho valor, colocaremos alguna otra cadena, en mi caso, mi sitio. La siguiente línea tiene un poco de truco. Resulta que me idea era procesar este script pasándolo por una regla de Rewrite de Apache. Sin embargo, cuando <code>mod_rewrite</code> recibe en la URL la cadena ‘http://’, la cambia, por seguridad y motivos similares, a ‘http:/’, entonces cuando estaba haciendo pruebas con este redireccionamiento, el script fallaba pues intentaba entrar a digamos, ‘http:/google.com’; entonces la segunda línea es un hack para este comportamiento. ¿Pero qué hace la expresión regular? Bueno, hace un <em>search and replace</em>, en la cadena busca aquello que empieza con ‘http’, después puede contener o no (es decir, cero o una vez) la ’s’ -y ésto a su vez lo cachamos con un paréntesis-, seguido de dos puntos y una diagonal, que puede estar una o dos veces. Todo eso lo cambiamos por ‘http’, el valor que cachamos en el paréntesis, <code>$1</code>, dos puntos y dos diagonales. Lo hacemos las veces que sea necesario implementando el modificador ‘g’. Entonces, si recibimos ‘https:/google.com’ lo cambiará a ‘https://google.com’; y si recibimos ‘http://www.damog.net’, lo cambiará a, exactamente lo mismo, ‘http://www.damog.net’.
</p>
<pre> &amp;wrong($url) unless is_http_uri($url) || is_https_uri($url);</pre>
<p>
Llamamos a la subrutina <code>wrong()</code>, pasándole la URL, a menos que sea una URI de HTTP o de HTTPS válida. <code>is_http_uri</code> e <code>is_https_uri</code> nos devolverán indefinido, en caso de que falle la validación y lanzarán <code>wrong</code>, que lo único que hace realmente es imprimir un error en el <em>browser</em>. Veremos la subrutina unas cuantas líneas abajo. Antes pudimos haber guardado en base de datos, utilizar la variable <code>$ENV{REMOTE_ADDR}</code> o muchas cosas, usted decida.
</p>
<pre> print "Location: $url", "\n\n";</pre>
<p>
Éste es un header que tenemos que colocar en la respuesta del cliente, para que el servidor tome la nueva URL y se haga una redirección. El usuario siempre debe recordar que los <em>headers</em> son colocados hasta cuando se encuentren dos nuevas líneas. De otra forma, nuestro servidor web local no definirá dónde acaban las cabeceras y no terminará la ejecución con error. Hasta este punto pasamos las validaciones y le aplicamos el <em>hack</em> para corregir el inconveniente con <code>mod_rewrite</code>. Desde luego que verificar si la URL es válida, es decir, que la URL nos lleve realmente a algún lado o página con contenido válido o que el servidor remoto esté efectivamente funcionando, está fuera del contexto de esta columna, nosotros simplemente cuando nos llega la petición tomamos la URL y colocamos un encabezado en nuestra respuesta en la comunicación HTTP. ¿Lindo, no? <img src="http://www.damog.net/wp-includes/images/smilies/icon_smile.gif" alt=":-)"/> Puedes usar algunos otros métodos para validar si la URL remota realmente es válida, quizás usando Net::Ping.</p>
<p>Ahora, veamos la subrutina <code>wrong</code>.
</p>
<pre> sub wrong {
my ($url) = shift;
print "Content-Type: text/plain", "\n\n";
print "It looks like $url is not a valid URL!";
exit;
}</pre>
<p>
Tomamos la variable <code>$url</code> con la URL que le pasamos. <code>shift</code> saca el primer elemento de un arreglo, en este caso <code>@_</code>. Y listo, imprimimos un mensaje en pantalla. Hay que colocar una cabecera <code>Content-Type</code>, dejar doble línea y ponemos el mensaje. Luego buscamos la puerta de salida y terminamos.</p>
<p>Hasta ahora es bastante simple y bien programado. Podemos probar la funcionalidad yendo hacia: <code><a href="http://www.damog.net/cgi-bin/redir.cgi?url=http://www.google.com">http://www.damog.net/cgi-bin/redir.cgi?url=http://www.google.com</a></code> o cualquier otra URL, inténtelo. Incluso podríamos poner una formita web, pues <code>param()</code> puede tomar, como ya lo decía argumentos POST o GET, indistintamente.</p>
<p>Como quiero empezar a usar este método para hacer ligas desde mi sitio a otros y quiero que tenga una mejor apariencia que esa URL larga y fea, hago uso de <code>mod_rewrite</code> y coloco un <code>.htaccess</code> en mi servidor web:
</p>
<pre> &lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteRule ^-&gt;(.*)$ /cgi-bin/redir.cgi?url=$1 [L]
&lt;/IfModule&gt;</pre>
<p>
Con dicha regla lo que hago es que cuando reciba una URL con una flechita (`-&gt;’), tomaré lo que venga a continuación y lo consideraré una URL, que es lo que le pasaré al <code>redir.cgi</code>. Entonces, puedo llamar <a href="../-%3Ehttp://www.google.com"><a href="http://www.damog.net/-&gt;http://www.google.com">http://www.damog.net/-&gt;http://www.google.com</a></a> y hará lo que quiero que haga, la ejecución del CGI con la URL como parámetro, y con la flechita se ve muy intuitivo.</p>
<p>¿Qué tal implementar además, logs o escritura en base de datos, o algo así? Inténtalo, la imaginación es el límite. Me gustaría mucho leer sus comentarios.
</p>
<h3>
<a title="referencias_   tiles" name="referencias_%20%20%20tiles" id="referencias_   tiles"></a>Referencias útiles</h3>
<ul>
<li><a href="http://httpd.apache.org/docs/2.0/howto/cgi.html"><a href="http://httpd.apache.org/docs/2.0/howto/cgi.html">http://httpd.apache.org/docs/2.0/howto/cgi.html</a></a></li>
<li><a href="http://www.cherokee-project.com/doc/CGI_executing.html"><a href="http://www.cherokee-project.com/doc/CGI_executing.html">http://www.cherokee-project.com/doc/CGI_executing.html</a></a></li>
<li><a href="http://search.cpan.org/%7Esonnen/Data-Validate-URI-0.01/lib/Data/Validate/URI.pm"><a href="http://search.cpan.org/~sonnen/Data-Validate-URI-0.01/lib/Data/Validate/URI.pm">http://search.cpan.org/~sonnen/Data-Validate-URI-0.01/lib/Data/Validate/URI.pm</a></a></li>
<li><a href="http://search.cpan.org/%7Ebbb/Net-Ping-2.31/lib/Net/Ping.pm"><a href="http://search.cpan.org/~bbb/Net-Ping-2.31/lib/Net/Ping.pm">http://search.cpan.org/~bbb/Net-Ping-2.31/lib/Net/Ping.pm</a></a></li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html</a></a></li>
<li><a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html"><a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html">http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html</a></a></li>
<li><a href="http://www.damog.net/gallery/v/edinburgh"><a href="http://www.damog.net/gallery/v/edinburgh">http://www.damog.net/gallery/v/edinburgh</a></a></li>
</ul>
<h2>
<a title="autor" name="autor" id="autor"></a>Autor</h2>
<p>
Durante el día, David Moreno Garza (<a href="http://www.damog.net//"><a href="http://www.damog.net/">http://www.damog.net/</a></a>) desarrolla aplicaciones, sistemas y proyectos para una incipiente empresa internacional de telecomunicaciones; adicionalmente es consultor independiente en empresas mexicanas y extranjeras utilizando Perl. Durante la noche intenta salvar al mundo del mal usando expresiones regulares y <em>netiquette</em>.
</p>
<h2>
<a title="licencia_de_uso" name="licencia_de_uso" id="licencia_de_uso"></a>Licencia de uso</h2>
<p>
Copyright © 2007 David Moreno Garza.</p>
<p>This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <a href="http://www.opencontent.org/openpub/"><a href="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</a></a>).</p>
<hr />
<h1>
<a title="sobre_la_columna_pl" name="sobre_la_columna_pl" id="sobre_la_columna_pl"></a>Sobre <em>La Columna.pl</em><br />
</h1>
<p><em>La Columna.pl</em>
<p> es una columna quincenal que escribe el autor alrededor de Perl. Está inspirado en las columnas que Randal L. Schwartz ha escrito desde hace varios años ya. Por medio de recetas, consejos, instructivos y guías, el autor pretende propiciar interés en la gente para que conozca un poco más a fondo este apasionante lenguaje de programación y así fomentar una comunidad más sólida alrededor de él.</p>
<p>Visite <a href="http://www.damog.net/columnapl"><a href="http://www.damog.net/columnapl">http://www.damog.net/columnapl</a></a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/redirecciones/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Manejo del tiempo con Perl</title>
		<link>http://stereonaut.net/manejo-del-tiempo-con-perl/</link>
		<comments>http://stereonaut.net/manejo-del-tiempo-con-perl/#comments</comments>
		<pubDate>Sat, 01 Sep 2007 03:46:54 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/08/manejo-del-tiempo-con-perl/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<h2>
<strong>Manejo</strong> <strong>del</strong> <strong>tiempo</strong> <strong>con</strong> <strong>Perl</strong><br />
</h2>
<p><a href="http://www.damog.net/columnapl" target="_blank">La Columna.pl</a> #1 &#8211; Mayo 21, 2007.</p>
<p>Recientemente, por algunas de las necesidades que <a href="http://www.maggit.com.mx/" target="_blank">tuvimos</a> en el trabajo, necesitamos manejar de alguna forma fechas y horas desde nuestros scripts y aplicaciones en <a href="http://www.perl.com/pub/a/1999/03/pm.html" target="_blank"><strong>Perl</strong></a>. Hace no-sé-cuántos años, los franceses propusieron un sistema decimal para manejar el <strong>tiempo</strong>, pero el método fue impopular entre la comunidad científica. Si hubiera sido así, manejar las fechas y horas en cualquier sistema, hubiera sido tan fácil que no habría tantas implementaciones para trabajar <strong>con</strong> él, como hoy en día. Pero bueno, el hubiera no existe.</p>
<p>En <strong>Perl</strong> a veces nos confunde sobre si necesitamos usar <a href="http://perldoc.perl.org/functions/localtime.html" target="_blank">localtime</a>, <a href="http://perldoc.perl.org/functions/time.html" target="_blank">time</a>, <a href="http://perldoc.perl.org/functions/gmtime.html" target="_blank">gmtime</a>, <a href="http://search.cpan.org/%7Edrolsky/DateTime-0.37/lib/DateTime.pm" target="_blank">DateTime.pm</a>, etc. para trabajar <strong>con</strong> el <strong>tiempo</strong>. En realidad es mucho más sencillo de lo que parece. Espero que estas minirecetas le sirvan a alguien cuando encuentre este texto buscando por ahí en la red el <strong>manejo</strong> <strong>del</strong> <strong>tiempo</strong> <strong>con</strong> <strong>Perl</strong>. Lo haré a manera de FAQ.</p>
<p>¿Cómo obtengo la fecha actual?<br />
La función localtime nos devuelve la fecha actual, pero lo hace en forma de una lista de 9 elementos que podemos obtener de una manera sencilla:</p>
<p>my @fecha = localtime; # La lista tiene el formato (seg, min, hora, día mes, mes, año, día sem, día año, DST).</p>
<p>De esta forma, cada uno de los elementos <strong>del</strong> arreglo @fecha, será, por orden, el de ese formato, de ahí podrías usar $fecha[0] para obtener el segundo, $fecha[1] para los minutos, y así sucesivamente. Puedes obtener más información en perldoc -f localtime.</p>
<p>¿Y time? ¿Qué es? ¿Cuándo lo utilizo? ¿localtime no se mandaba llamar como localtime(time)?</p>
<p>La función time nos regresa la cantidad de segundos desde el epoch, léase, el 1 de enero de 1970, UTC, como en la mayoría de los sistemas actuales. time realmente lo hace desde cualquier epoch de acuerdo a la arquitectura de la máquina, pero supondremos que ese no es el caso.</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘print time.”\n”;’<br />
1179168385<br />
localtime toma como parámetro una cierta cantidad de segundos. Por default, toma el valor de time. Así que podemos usar tanto localtime como localtime(time) cuando usemos dicha función.</p>
<p>Pero lo que yo quiero es obtener la fecha en el formato que yo quiera.</p>
<p>Tienes dos opciones. Una, es usar el contexto escalar de localtime, es decir, tratar lo que nos regresa localtime como una variable escalar, no como una lista. Ejemplo:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘$fecha = localtime; print $fecha, “\n”;’<br />
Wed May 16&#160;19:29:55&#160;2007<br />
damog@cochina:~$</p>
<p>Sencillo, ¿no? Lo cual es lo mismo que usar la función scalar, sin tener que asignar forzosamente a una variable escalar:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘print scalar localtime, “\n”‘<br />
Wed May 16&#160;19:30:55&#160;2007<br />
damog@cochina:~$</p>
<p>Puedes echar un ojo a <a href="http://perldoc.perl.org/perllocale.html" target="_blank">perllocale</a> si es que la fecha te interesa en otro idioma.</p>
<p>Lo más sencillo, desde mi muy personal punto de vista, y la otra opción, es usar strftime. No hay que temer a usarlo, básicamente utiliza la misma sintaxis que su predecesor, strftime de C. A final de cuentas es bien sencillo (incluso a veces yo echo un rápido vistazo a la página de strftime de PHP que explica cómo usar la función y es la misma implementación). Esta función se encuentra en el módulo estándar <a href="http://perldoc.perl.org/POSIX.html" target="_blank">POSIX</a>, que podría ser que ya tengas cargado en tu distribución o sistema operativo. Lo que strftime necesita, es el formato en el que necesitas la fecha, y el <strong>tiempo</strong> en segundos desde el epoch.</p>
<p>Supongamos que queremos la fecha <strong>del</strong> día de hoy, en el formato AAAA-MM-DD:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use POSIX qw(strftime);<br />
&gt; print strftime(”%Y-%m-%d”, localtime), “\n”;<br />
&gt; ‘<br />
2007-05-17<br />
damog@cochina:~$</p>
<p>¿Muy simple, no?</p>
<p>Incluso, si queremos hacer un poco de matemáticas <strong>con</strong> días, lo podemos hacer <strong>con</strong> strftime, por ejemplo, queremos la fecha de ayer en formato AAAA-MM-DD hh-mm-ss:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use POSIX qw(strftime);<br />
&gt; print strftime(”%Y-%m-%d %H:%M:%S”, localtime(time &#8211; 86400)), “\n”;<br />
&gt; ‘<br />
2007-05-16&#160;10:14:06<br />
damog@cochina:~$<br />
Como que no entendí muy bien eso de los contextos de localtime. ¿Me lo podrías aclarar?</p>
<p>Claro. localtime es manejado por <strong>Perl</strong> desde dos conceptos para su valor de retorno. Uno es el contexto de escalar y uno en el contexto de lista (como sabes, <strong>Perl</strong> utiliza estos dos tipos -u otros- de conceptos para el <strong>manejo</strong> de sus variables). El contexto escalar de localtime es el que nos regresa una fecha formateada (puedes echar un ojo también a la función scalar, si tienes duda al respecto); el contexto de lista de localtime nos regresa un arreglo, donde cada uno de sus elementos, corresponde a un atributo de la fecha, como la documentación de la función nos lo indica y como lo indicaba líneas arriba. Es bien simple.</p>
<p>De hecho, los conceptos de escalar y lista es muy simple. Una variable escalar puede contener cadenas, valores numéricos, referencias, etc. Una variable de lista son arreglos, los cuales, a su vez, contienen elementos escalares, listados en ellos. Como una nota al margen, actualmente las variables escalares de las listas son manejadas de la forma $arreglo[2], por ejemplo, así es como <strong>Perl</strong> 5 lo maneja. En <a href="http://dev.perl.org/perl6/" target="_blank"><strong>Perl</strong> 6</a> se utilizarán los elementos de las listas de la forma @arreglo[2], lo cual es mucho más intuitivo y natural, pero mientras <strong>Perl</strong> 6 no vea la luz oficialmente, esta nota queda sólo como una acotación adicional <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Aún se me hace un poco complicado, ¿no hay una forma más fácil?</p>
<p>¡Desde luego! There is more than one way to do it. Hay una cantidad enorme de módulos de fecha y hora disponibles en <a href="http://search.cpan.org/">CPAN</a>, sin embargo, el que ha gozado de gran aceptación por su buena implementación y diseño, es DateTime.</p>
<p><strong>Con</strong> DateTime podemos manejar fechas y tiempos en una forma mucho más natural e intuitiva, podemos hacer operaciones matemáticas de una forma mucho más lingüística, que puede terminar ayudando mucho más la naturaleza y la lógica de nuestros programas:</p>
<p>¿Cómo puedo obtener la hora actual <strong>con</strong> DateTime?</p>
<p>Bien simple:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use DateTime;<br />
&gt;<br />
&gt; my $hoy = DateTime-&gt;now();<br />
&gt; print $hoy, “\n”;<br />
&gt; ‘<br />
2007-05-17T16:26:12<br />
damog@cochina:~$</p>
<p>Sin embargo, hay que ser un poco cuidadosos al usar el método now() pues nos regresa la fecha en UTC. Para eso, podemos crear el objeto $hoy, especificando nuestra zona horaria:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use DateTime;<br />
&gt; my $hoy = DateTime-&gt;now(time_zone =&gt; “America/Chicago”);<br />
&gt; print $hoy, “\n”;<br />
&gt; ‘<br />
2007-05-17T11:29:51<br />
damog@cochina:~$</p>
<p>Ese objeto, puede ser utilizado para muchas más cosas. Por ejemplo, a una fecha, sumarle un mes, no es lo mismo que sumarle 28 días, ó 30, ó 31. Mira este ejemplo, donde crearemos un objeto DateTime <strong>con</strong> una fecha en el pasado y le sumaremos un mes y luego le restaremos dos años:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use DateTime;<br />
&gt; my $fecha = DateTime-&gt;new(<br />
&gt; year =&gt; 1984,<br />
&gt; month =&gt; 8,<br />
&gt; day =&gt; 8,<br />
&gt; hour =&gt; 2,<br />
&gt; minute =&gt; 0);<br />
&gt; print $fecha-&gt;add(months =&gt; 1), “\n”;<br />
&gt; print $fecha-&gt;add(years =&gt; -2), “\n”;<br />
&gt; print “DateTime es la onda!\n”;<br />
&gt; ‘<br />
1984-09-08T02:00:00<br />
1982-09-08T02:00:00<br />
DateTime es la onda!<br />
damog@cochina:~$</p>
<p>Podemos ver que creamos un objecto DateTime llamado $fecha que apunta hacia el 8 de agosto de 1984, 2 de la mañana. A él, le sumamos un mes y luego le restamos dos años. Simple, ¿no crees?</p>
<p>¿Y cómo puedo hacer una diferencia de fechas?</p>
<p>Creo que lo más sencillo para utilizar, es Date::Manip. Observa este ejemplo:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use Date::Manip;<br />
&gt; my $hoy = ParseDate(”today”);<br />
&gt; my $fecha_nacimiento = ParseDate(”1984-08-08&#160;02:00:00″);<br />
&gt; $delta = DateCalc($fecha_nacimiento, $hoy, \$err, 1);<br />
&gt; print $delta, “\n”;<br />
&gt; ‘<br />
+22:9:1:2:9:55:34<br />
damog@cochina:~$</p>
<p>Básicamente, creamos dos cadenas, $hoy y $fecha_nacimiento y luego las pasamos por &amp;DateCalc, que requiere ambas fechas, una referencia a una variable de error y la variable 1, como modo de operación que nos hará la diferencia entre ambas fechas. Esto nos regresa una cadena parseable para el método &amp;ParseDateDelta, cuyo formato nosotros podemos utilizar y parsear:</p>
<p>my ($anos, $meses, $semanas, $dias, $horas, $minutos, $segundos)</p>
<p>= $delta =~ /^\+(\d+):(\d+):(\d+):(\d+):(\d+):(\d+):(\d+)$/;</p>
<p>Echando rápidamente una mirada a la cadena, podemos saber que en el momento de escribir esta guía, tengo 22 años, 9 meses, 1 semana, 2 días, 9 horas, 55 minutos y 34 segundos de vida. <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>¿Pero y si quiero convertir una cierta fecha a segundos desde el epoch?</p>
<p>El módulo POSIX también proporciona una función bien sencilla llamada <a href="http://perldoc.perl.org/POSIX.html" target="_blank">mktime</a> que puede ser usada para precisamente esto.</p>
<p>Como puede verse en la documentación de esta función, la sintaxis es la siguiente:</p>
<p>mktime(sec, min, hour, mday, mon, year, wday = 0, yday = 0, isdst = 0);</p>
<p>Quiero saber la cantidad de segundos hasta el momento que mis padres me han dicho que nací, 2 am, <strong>del</strong> 8 de agosto de 1984. El valor mon es contabilizado desde 0, el cual es enero, y así sucesivamente hasta el 11 que es diciembre. De forma similar <strong>con</strong> wday y yday. El argumento year, empieza desde 1900. Dicho lo anterior, podemos calcular:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use POSIX qw(mktime);<br />
&gt;<br />
&gt; print mktime(0, 0, 2, 8, 7, 84), “\n”;<br />
&gt; ‘<br />
460800000<br />
damog@cochina:~$</p>
<p>Ahí utilizamos 0 para el segundo, 0 para el minuto, 2 para la hora, 8 para el día <strong>del</strong> mes, 7 para el mes <strong>del</strong> año (agosto, recordemos que empiezan desde cero) y 84 para el año desde 1900. Nací en el segundo 460800000 desde el epoch. Pero vamos a ver si eso es cierto, usaremos una combinación de mktime y localtime, en su contexto escalar:</p>
<p>damog@cochina:~$ <strong>perl</strong> -e ‘<br />
&gt; use POSIX qw (mktime);<br />
&gt;<br />
&gt; print scalar localtime(mktime(0, 0, 2, 8, 7, 84)), “\n”;<br />
&gt; ‘<br />
Wed Aug  8&#160;02:00:00&#160;1984<br />
damog@cochina:~$</p>
<p>Parece que así es <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Nací en el segundo  460800000. Era miércoles <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Como puedes ver, no es la gran cosa procesar fechas y horas en <strong>Perl</strong>, realmente es sencillo y sólo es cosa de excarvarle un poquito por aquí y por allá y usar cinta adhesiva para obtener lo que queremos de una forma eficiente y útil.</p>
<p>Ojalá te sirva, espero que te hayas divertido aprendiendo un poquito sobre el <strong>tiempo</strong> en <strong>Perl</strong> así como yo me divertí escribiendo. Puedes hacerme llegar tus comentarios a &lt;<a href="mailto:damog@ciencias.unam.mx" target="_blank">damog@ciencias.unam.mx</a>&gt;.</p>
<p>Información extendida recomendada:
</p>
<ul>
<li><a href="http://www.perl.com/pub/a/2003/03/13/datetime.html" target="_blank">The Many Dates and Times of <strong>Perl</strong></a></li>
<li><a href="http://perl.about.com/od/perltutorials/a/perllocaltime.htm" target="_blank">How to tell the current time in <strong>Perl</strong></a></li>
<li><a href="http://www.stonehenge.com/merlyn/UnixReview/col25.html" target="_blank">Getting a date with <strong>Perl</strong></a></li>
<li><a href="http://datetime.perl.org/?FAQ" target="_blank">DateTime Project FAQ</a></li>
</ul>
<hr />
<p>
Sobre el autor: Durante el día, David Moreno Garza (<a href="http://www.damog.net//" target="_blank">damog</a>) desarrolla aplicaciones, sistemas y proyectos para una incipiente empresa internacional de telecomunicaciones; adicionalmente es consultor independiente en empresas mexicanas y extranjeras utilizando <strong>Perl</strong>. Durante la noche intenta salvar al mundo <strong>del</strong> mal usando expresiones regulares y netiquette.
</p>
<hr />
<p>
Copyright © 2007 David Moreno Garza.This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <a href="http://www.opencontent.org/openpub/"><a href="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</a></a>). </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/manejo-del-tiempo-con-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pequeñas herramientas para grandes necesidades</title>
		<link>http://stereonaut.net/pequenas-herramientas-para-grandes-necesidades/</link>
		<comments>http://stereonaut.net/pequenas-herramientas-para-grandes-necesidades/#comments</comments>
		<pubDate>Sat, 01 Sep 2007 03:44:51 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/08/pequenas-herramientas-para-grandes-necesidades/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p id="post-664"><strong>Pequeñas herramientas para grandes necesidades</strong></p>
<ul>
<li>
<a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#la_columna_pl__2">La <strong>Columna</strong>.<strong>pl</strong> #<strong>2</strong></a></p>
<ul>
<li>
<a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#peque%20%20%20_as_herramientas_para_grandes_necesidades">Pequeñas herramientas para grandes necesidades</a></p>
<ul>
<li><a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#referencias_%20%20%20%20%20%20tiles">Referencias útiles</a></li>
</ul>
</li>
<li><a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#autor">Autor</a></li>
<li><a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#licencia_de_uso">Licencia de uso</a></li>
</ul>
</li>
<li><a href="http://www.damog.net/columnapl/pequenas-herramientas-para-grandes-necesidades/#sobre_la_columna_pl">Sobre <em>La <strong>Columna</strong>.<strong>pl</strong></em></a></li>
</ul>
<hr />
<h1>
<a title="la_columna_pl__2" name="la_columna_pl__2" id="la_columna_pl__2"></a>La <strong>Columna</strong>.<strong>pl</strong> #<strong>2</strong><br />
</h1>
<h2>
<a title="peque   _as_herramientas_para_grandes_necesidades" name="peque%20%20%20_as_herramientas_para_grandes_necesidades" id="peque   _as_herramientas_para_grandes_necesidades"></a>Pequeñas herramientas para grandes necesidades</h2>
<p>
Se han pasado muy rápidamente estos últimos 15 días. Entre algunas pláticas, trabajo y otras cosas, pareciera que el tiempo simplemente se esfuma tan, tan rápidamente.</p>
<p>Como sea, ya estamos en la segunda entrega de <em>La <strong>Columna</strong>.<strong>pl</strong></em>. En esta quincena quiero tocar un tema bien interesante que son esas pequeñas herramientas que nos pueden llenar de una manera muy especial alguna de nuestras necesidades. ¿Hay algo por ahí que quieras automatizar pero no te decides? Inténtalo.</p>
<p>El ejemplo que voy a poner aquí es acerca de una pequeña utilidad que hice para revisar el estado de la batería de mi laptop. Como es bien sabido por algunos de ustedes, amables lectores, utilizo una máquina <em>PowerBook G4</em>, sobre <em>Debian GNU/Linux</em>: En esta máquina hago la mayoría de mi trabajo, que se basa principalmente en desarrollo de software y algo de administración de sistemas. La mayoría de mi trabajo lo hago en esta máquina que es casi tan estable como una piedra. En fin, las computadoras <em>Apple</em>, como ésta, utilizan un microcontrolador que gestiona las funcionalidades de energía, tales como el control de suspensión, el nivel de batería y otras similares, llamado PMU. Lamentablemente las aplicaciones actualmente existentes que monitorean los atributos de PMU, en Linux sobre estas computadoras no me satisfacen del todo: Algunas son unas aplicaciones en <em>GTK</em> verdaderamente estorbosas; otras están integradas al panel de control de <em>GNOME</em> o <em>KDE</em>, del cual no utilizo ninguno. Opté por utilizar el control de batería de <em>GKrellM</em>, que es algo modesto, pero que de todas formas a veces no quería tener siempre en mi escritorio &#8211; que para empezar, no es que tenga un escritorio como tal, pues de un escritorio sólo utilizo algunos escritorios virtuales y algo de soporte de systray. Finalmente no estaba muy seguro de lo que necesitaba. Lo único seguro era mi inseguridad en el caso <img src="http://www.damog.net/wp-includes/images/smilies/icon_smile.gif" alt=":-)"/></p>
<p>¡Una pequeña aplicación en Perl! Claro, desde un emulador de terminal podría llamar esta aplicación y me diría qué porcentaje tengo de batería restante en mi máquina, sería lo más simple, sencillo y a mi gusto, sería perfecto. Pues vamos a poner las manos a la obra.</p>
<p>En mi máquina, la información de la batería se encuentra en /proc/pmu/battery_0, que luce así:
</p>
<pre> flags      : 00000011 charge     : 3535

max_charge : 3537

current    : 0

voltage    : 12495

time rem.  : 0</pre>
<p>
El archivo indica diferentes valores para amperaje y voltaje. Los que me interesan son los valores de charge y max_charge que indican miliampers/hora de la carga actual que tiene la pila y la máxima.</p>
<p>Lo que hay que hacer es bastante simple. Obtener el valor de charge, el de max_charge y obtener un porcentaje del primero con respecto al segundo. En esta columna tocaré algunos temas básicos pero que pueden ser de utilidad para entender algunos conceptos más adelante en otras columnas.
</p>
<pre> #!/usr/bin/perl use warnings;

use strict;</pre>
<p>
Mando llamar al intérprete de Perl que en la mayoría de las distribuciones con binarios precompilados irá a dar a <code>/usr/bin/perl</code> e inmediatamente mando llamar dos pragmas de Perl: El primero, <code>warnings</code>, para controlar advertencias y el segundo, <code>strict</code>, para restringir construcciones inseguras. Es bueno siempre llamar ambos pragmas para educarnos un poco al programar. Un pragma es únicamente un indicador para el momento de la compilación, podremos estudiar un poco los pragmas en futuras columnas.
</p>
<pre> my $pmufile = '/proc/pmu/battery_0';</pre>
<p>
Declaro la variable <code>$pmufile</code> que indicará la ruta absoluta del archivo que mencionaba anteriormente.
</p>
<pre> my $filecont; {

local $/ = undef;

open(PMU, $pmufile) or die $!;

$filecont = &lt;PMU&gt;;

}</pre>
<p>
Aunque el uso de <code>local</code> ya no se aconseja mucho, es bueno a veces para utilizarlo en bloques específicos donde sólo tengamos que modificar, quizás, una variable especial, como en este caso, la variable especial <code>$/</code>. Esta variable nos sirve para definir el <em>input record separator</em>, que por default, es una línea nueva. Modificarlo nos permite hacer cosas interesantes, sobre todo cuando efectuamos un ciclo <code>while()</code> hacia un filehandle. En este caso, indefinimos su valor, por lo cual, luego de abrir el archivo <code>$filename</code> a lectura, vaciamos todo el contenido del archivo en una sola variable, <code>$filecont</code>, que habíamos declarado antes del bloque. En alguna columna futura tengo pensado tratar a fondo las variables especiales, que son algo muy interesante dentro de Perl.
</p>
<pre> my($charge) = $filecont =~ /charges+:s(d+)/; my($max_charge) = $filecont =~ /max_charges+:s(d+)/;</pre>
<p>
Aquí creamos las variables <code>$charge</code> y <code>$max_charge</code> y les asignamos el valor que nos arroja nuestra expresión regular como la variable especial <code>$1</code>, en ambas líneas.
</p>
<pre> my $porc = int (($charge/$max_charge) * 100);</pre>
<p>
Dividimos <code>$charge</code> entre <code>$max_charge</code> y multiplicamos el resultado por cien, para obtener el porcentaje. Sin embargo, este resultado nos arrojaría más de diez decimales, después del punto. Por ello, utilizamos la función de Perl, <code>int</code>, que nos regresa el valor entero de su parámetro (mi incipiente naturaleza matemática me hace hacer notar que un número entero no es necesariamente un número natural <img src='http://stereonaut.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ).
</p>
<pre> print "t", "Restante: $porc %", "n";</pre>
<p><code>print</code>
<p> en realidad requiere una lista como argumento, lo que generalmente hacemos en enviarle un sólo parámetro (por ejemplo, <code>print "Hola mundo";</code>), sin embargo, para una notación mucho más intuitiva, ponemos el salto de línea y el tabulador como primer y tercer parámetro, una lista, precisamente.</p>
<p>¡Y listo! Le agrego un bit de ejecución al script, lo renombro a <code>pila</code>, lo pongo en <code>/usr/local/bin</code> o algo similar y puedo correrlo fácilmente:
</p>
<pre> damog@cochina:~$ pila         Restante: 86 %

damog@cochina:~$</pre>
<p>
Ya luego podría usar ese comando para hacer otras cosas: parsear el valor y podría enviarme un correo avisándome que ya se me va a acabar la pila, o mandar un mensaje al systray o quizás conectarme al IRC y avisarle a mi nick al respecto; hay muchas cosas más que Perl nos facilita hacer, ¡tu imaginación es el límite!</p>
<p>De otras muchas formas habríamos podido abrir el archivo y leer el contenido de <code>charge</code> y <code>max_charge</code>. ¿Tú de qué forma lo hubieras hecho? ¿Quizás ciclar el filehandle hasta toparse con <code>/^max_charge/</code>? ¿Quizás usar alguna combinación con ejecución externa de <code>cat</code> o de <code>grep</code>?</p>
<p>Te invito a que me envíes tus comentarios. Nos leemos dentro de quince días.
</p>
<h3>
<a title="referencias_      tiles" name="referencias_%20%20%20%20%20%20tiles" id="referencias_      tiles"></a>Referencias útiles</h3>
<ul>
<li><a href="http://perldoc.perl.org/index-pragmas.html"><a href="http://perldoc.perl.org/index-pragmas.html">http://perldoc.perl.org/index-pragmas.html</a></a></li>
<li><a href="http://perldoc.perl.org/perlvar.html"><a href="http://perldoc.perl.org/perlvar.html">http://perldoc.perl.org/perlvar.html</a></a></li>
<li><a href="http://perldoc.perl.org/functions/int.html"><a href="http://perldoc.perl.org/functions/int.html">http://perldoc.perl.org/functions/int.html</a></a></li>
<li><a href="http://perldoc.perl.org/perlop.html#Integer-Arithmetic-integer"><a href="http://perldoc.perl.org/perlop.html#Integer-Arithmetic-integer">http://perldoc.perl.org/perlop.html#Integer-Arithmetic-integer</a></a></li>
</ul>
<h2>
<a title="autor" name="autor" id="autor"></a>Autor</h2>
<p>
Durante el día, David Moreno Garza (<a href="http://www.damog.net//"><a href="http://www.damog.net/">http://www.damog.net/</a></a>) desarrolla aplicaciones, sistemas y proyectos para una incipiente empresa internacional de telecomunicaciones; adicionalmente es consultor independiente en empresas mexicanas y extranjeras utilizando Perl. Durante la noche intenta salvar al mundo del mal usando expresiones regulares y <em>netiquette</em>.
</p>
<h2>
<a title="licencia_de_uso" name="licencia_de_uso" id="licencia_de_uso"></a>Licencia de uso</h2>
<p>
Copyright © 2007 David Moreno Garza.</p>
<p>This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at <a href="http://www.opencontent.org/openpub/"><a href="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</a></a>).</p>
<hr />
<h1>
<a title="sobre_la_columna_pl" name="sobre_la_columna_pl" id="sobre_la_columna_pl"></a>Sobre <em>La <strong>Columna</strong>.<strong>pl</strong></em><br />
</h1>
<p><em>La <strong>Columna</strong>.<strong>pl</strong></em>
<p> es una columna quincenal que escribe el autor alrededor de Perl. Está inspirado en las columnas que Randal L. Schwartz ha escrito desde hace varios años ya. Por medio de recetas, consejos, instructivos y guías, el autor pretende propiciar interés en la gente para que conozca un poco más a fondo este apasionante lenguaje de programación y así fomentar una comunidad más sólida alrededor de él.</p>
<p>Visite <a href="http://www.damog.net/columnapl"><a href="http://www.damog.net/columnapl">http://www.damog.net/columnapl</a></a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/pequenas-herramientas-para-grandes-necesidades/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La Columna.pl</title>
		<link>http://stereonaut.net/la-columnapl/</link>
		<comments>http://stereonaut.net/la-columnapl/#comments</comments>
		<pubDate>Sat, 01 Sep 2007 03:32:25 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/08/la-columnapl/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><strong>La Columna.pl</strong> es una columna periódica en español sobre el lenguaje de programación y la cultura Perl.
</p>
<ul>
<li>
<a href="http://www.damog.net/la-columnapl/manejo-del-tiempo-con-perl/">La Columna.pl #1</a>. 26 de mayo de 2007. Manejo del tiempo con Perl.</li>
<li>
<a href="http://www.damog.net/la-columnapl/pequenas-herramientas-para-grandes-necesidades/">La Columna.pl #2</a>. 7 de junio de 2007. Pequeñas herramientas para grandes necesidades.</li>
<li>
<a href="http://www.damog.net/la-columnapl/redirecciones/">La Columna.pl #3</a>. 9 de julio de 2007. Redirecciones.</li>
<li>
<a href="http://www.damog.net/la-columnapl/automatizacion-en-web-con-wwwmechanize/">La Columna.pl #4</a>. 5 de septiembre de 2007. Automatización en web con WWW::Mechanize.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/la-columnapl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La Columna.pl #1</title>
		<link>http://stereonaut.net/la-columnapl-1/</link>
		<comments>http://stereonaut.net/la-columnapl-1/#comments</comments>
		<pubDate>Tue, 22 May 2007 03:08:40 +0000</pubDate>
		<dc:creator>David Moreno</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://log.damog.net/wp/2007/05/la-columnapl-1/</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p>La Columna.pl es una columna que estaré publicando quincenalmente. Ella, inspirada por la gran cantidad de <a href="http://www.stonehenge.com/merlyn/columns.html" target="_blank">columnas de Perl que ha escrito Randal Schwartz</a>, tocará diferentes temas y situaciones que principiantes o programadores en Perl pueden enfrentar y que yo personalmente también he enfrentado e intento explicar de una forma rápida, concisa y sencilla. Creo firmemente que, una vez digerida una curva pronunciada de aprendizaje, esa experiencia puede moldearse de tal forma que transforme la línea en lo más recta posible para gente interesada, para gente que desea conocer ejemplos de la vida real.</p>
<p>La Columna.pl de esta semana trata, como su título bien lo apunta, sobre el manejo del tiempo con Perl. El tiempo es algo que no siempre es lo suficientemente intuitivo para trabajar, su propia naturaleza lo hace complejo. Sumar una fecha con otra no es tan sencillo como puede parecer: Hay que tomar en cuenta muchas cosas, los meses con 30 ó 31 días, por ejemplo, los años bisiestos, incluso si hay un cambio de zonas horarias, pueden ser calculadas con el pasar de los años. El tiempo es a veces algo confuso cuando se maneja con Perl, pero es sólo por apariencia, en realidad es de lo más sencillo y divertido. Los invito a que estén al pendiente de La Columna.pl, cada quince días, pues pongo esfuerzo, dedicación y amor en este trabajo, para obtener un producto de calidad que le guste y le sirva a la gente.</p>
<p>Naturalmente, le agradezco a <a href="http://maggit.com.mx/" target="_blank">mi reina</a> su apoyo en este proyecto, pues ella fue mi inspiración inicial; y asimismo, le agradezco a <a href="http://www.unixmonkeys.org/amnesiac">Marco Antonio Manzo</a> por sus siempre puntuales observaciones y apoyo para la difusión de Perl. Y desde luego, a <a href="http://www.stonehenge.com/merlyn/" target="_blank">merlyn</a>, por servir como modelo a seguir.</p>
<p align="center"><a href="http://www.damog.net/columnapl"><a href="http://www.damog.net/columnapl">http://www.damog.net/columnapl</a></a> </p>
]]></content:encoded>
			<wfw:commentRss>http://stereonaut.net/la-columnapl-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

