<?xml version="1.0" encoding="utf8"?>
<!DOCTYPE html
	PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
	 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<HTML>
<HEAD>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=uft8">
   <META NAME="DATE" CONTENT="11/2/2003">
   <META NAME="Author" CONTENT="J. J. Merelo">
   <META NAME="Description" CONTENT="Tutorial de PERL en castellano, con ejemplos y ejercicios">
   <META NAME="Keywords" CONTENT="curso de perl, tutorial de perl, manual de perl, programacion"> 
   <TITLE>Tutorial de Perl:  Recordando, que es gerundio  </TITLE>
<script language="JavaScript">
var contador = 1;
var contadores= new Array;
function multicontador(  numero ) {
      if ( ! contadores[ numero ]  )
          contadores[ numero ] = 1;
      else
          contadores[numero ]++;
      document.write( contadores[numero] );
};

</script>
<link rel ='stylesheet' type = "text/css" href = "perl.css">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#ffffff" LINK="#0000FF" VLINK="#551A8B" ALINK="#FF0000">
<TABLE  align=center cellpadding=5 bgcolor='darkseagreen'>
	<tr>

	<td>
			 <!-- Atomz.com Search HTML for Tutorial de PERL en castellano -->
	  <form method="get" action="http://search.atomz.com/search/">
	    <input size=25 name="sp-q"><br /><input type=submit value="Busca en el tutorial">
	    <input type=hidden name="sp-a" value="0002147b-sp00000001">
	  </form>
	</td>

	<td align='center'>
			<h1><a href='indice.html'>Tutorial de <strong>PERL</strong> en castellano </a>: Recordando, que es gerundio</h1>
	</td>

    <td align='right' valign='top'><a href='tutoperl16.html'> Preguntas frecuentemente preguntadas</a><br><a href='tutoperl17.html'> Bibliograf&iacute;a.</a><br><a href='tutoperl18.html'> Recursos Internet</a><br><a href='tutoperl8.html'> Purgando los pecados.</a><br></td>
	</tr>
</table>

<h3>La orden <code>split</code>, matrices asociativas y matrices bidimensionales</h3>



<P>Al final del d&iacute;a, nuestro pol&iacute;tico corrupto reflexiona.
&iquest;De qu&eacute; sirve tanto trabajo, sin una buena contabilidad consolidada?
(Adem&aacute;s, tiene que presentarle las cuentas al se&ntilde;or X a fin
de mes). Idea, pues, el <a href='totales.pl.html'>programa que aparece en el listado 4</a>.

<table class=listado align=center cellspacing=0 border=0 cellpadding=1><tr><td
bgcolor=black ><table width=100  cellspacing=0 border=0 cellpadding=1 ><tr><td bgcolor=white>
<pre><font size=+2>
1&nbsp;<font color=blue><font color=red>die</font></font> "Y el fichero de clientes, ein?\n" <font color=blue>unless</font> <font color=green>$ARGV</font>[0];
2&nbsp;<font color=blue>while</font>(&lt;&gt;) {
3&nbsp;  <font color=green>@linea</font> = <font color=red>split</font>;
4&nbsp;  <font color=green>@fecha</font>=<font color=red>split</font>(/\//,<font color=green>$linea</font>[$#<em>linea]);
</em>5&nbsp;  <font color=green>$mesdia</font> = "<font color=green>$fecha</font>[1]-<font color=green>$fecha</font>[0]";
6&nbsp;  <font color=green>$pasta</font>=<font color=green>$linea</font>[$#<em>linea - 2];
</em>7&nbsp;  <font color=green>$totalDia</font>{<font color=green>$mesdia</font>}+=<font color=green>$pasta</font>;
8&nbsp;}
9&nbsp;
10&nbsp;<font color=blue>foreach</font> (<font color=red>sort</font> <font color=red>keys</font> <font color=green>%totalDia</font>) {
11&nbsp;  <font color=red>print</font> "Trinque total del dia <font color=green>$_</font> = <font color=green>$totalDia</font>{<font color=green>$_</font>}\n";
12&nbsp;}
</font></pre>

</td></tr></table></td></tr><caption><font face="arial,helvetica">Listado <script>multicontador(1);</script>: Programa totales.pl</font></caption></table>

<P> Este
programa, aplicado sobre el fichero <a href=clientes.mas><code>clientes.mas</code></a>, (resultado de una incursi&oacute;n
en la construcci&oacute;n de diversas viviendas para los cuerpos de seguridad
del estado y sus departamentos de investigaci&oacute;n y desarrollo, as&iacute;
como otros procedentes del mundo de la ense&ntilde;anza) da el siguiente
resultado (o algo parecido)<pre>
C:\PROGS\PERL>perl totales.pl clientes.mas
Trinque total del dia 3-24 = 598454.75
Trinque total del dia 4-25 = 1100987
Trinque total del dia 4-26 = 487775
</pre>

<P>Este programa empieza con una
advertencia: "muere si no me metes un fichero como argumento". La orden
<code>die</code> termina el programa con un mensaje; mientras
que el condicional que lo sigue comprueba que exista al menos un
argumento para el programa;
la matriz <code>@ARGV</code> contiene los argumentos pasados
al programa; de forma que <code>$#ARGV</code> dar&aacute;
el &iacute;ndice del &uacute;ltimo argumento, o sea que si es -1, indicar&aacute;
que no se ha pasado ning&uacute;n argumento. Y otra forma de hacerlo
ser&iacute;a <P><Pre>
die "Sin argumento me lamento\n" if $#ARGV &lt; 0;</pre>
<P>O incluso<p><pre>
$ARGV[0] || die "Te has quedado sin argumentos\n";
</pre>
<p>que mira lo que hay a la izquierda del <code>||</code> (que es el "o" 
lógico), y si es cierto, ejecuta lo que hay a la derecha. Recuerda, en 
<STRONG>PERL</STRONG> hay más bla, bla.</p>

<P>El siguiente bucle, que comienza en la <I>l&iacute;nea 2</I>, tiene
una extra&ntilde;a condici&oacute;n para que el bucle siga; s&oacute;lo
los dos &aacute;ngulos enfrentados. Te&oacute;ricamente, deber&iacute;a
de haber un <I>filehandle</I> dentro de esos &aacute;ngulos (como se
ha visto en un ejemplo anterior), pero en este
caso, se est&aacute; tomando el fichero por defecto, que es el fichero
que se introduce como argumento; en caso de que no se hubiera introducido
ninguno tomar&iacute;a entrada est&aacute;ndar, es decir, que habr&iacute;a
que introducirle cada l&iacute;nea mediante teclado. A la vez, y como se
ha visto, esa orden toma una l&iacute;nea del fichero y la deposita en
la variable por defecto, aunque, ojo, no le quita el retorno de carro
final. Hay que tener en cuenta que los paréntesis angulares sin
argumento extraen elementos del array <code>@ARGV</code> usando
<code>pop</code>, y abren un fichero con ese nombre; o sea que si
hubiera varios nombres de fichero en la línea de comandos, los iría abriendo uno 
por uno y disminuyendo consecuentemente el tamaño de
<code>@ARGV</code>; conclusión, que si necesitas <code>@ARGV</code>
para algo, mejor que lo guardes antes de meterte en un bucle de esta guisa.
</p>

<P>Sobre la variable por defecto act&uacute;a la orden <code>split</code>
(una de las cosas m&aacute;s usadas en <strong>PERL</strong>), dividi&eacute;ndola en una serie
de cadenas separadas por espacios y depositando cada una de esas cadenas
en un elemento de la matriz <code>@linea</code>. Y dese
cuenta el venerado p&uacute;blico de con qu&eacute; facilidad hemos hecho
algo que requerir&iacute;a al menos 10 l&iacute;neas de cualquier otro
lenguaje. No hay que dimensionar matrices, no hay que recorrer la cadena
caracter por caracter... &iexcl;Nada!<SUP><A HREF="#N_3_">(3)</A></SUP>.
Perd&oacute;n, me he dejado llevar por el entusiasmo.
</p>

<P>La fecha es, en todos los casos, la &uacute;ltima cadena de la l&iacute;nea;
es decir, que ser&aacute; el &uacute;ltimo elemento de la matriz (cuyo
sub&iacute;ndice es siempre <code>$#&lt;nombre-matriz)</code>),
pero a su vez tendremos que dividirlo, esta vez por la barra de separaci&oacute;n,
para luego poder poner el mes delante y que salga todo bellamente ordenado
por meses en vez de por d&iacute;as.
</p>

<P>Esta cadena con la fecha, m&aacute;s la pasta, que est&aacute; siempre
2 posiciones m&aacute;s a la izquierda (independientemente de la longitud
de los nombres), se utiliza en la l&iacute;nea 7 en una <B>matriz asociativa</B>.
Esta es otra de las caracter&iacute;sticas m&aacute;s potentes del <strong>PERL</strong>,
se pueden usar matrices cuyo &iacute;ndice es una cadena cualquiera, no
s&oacute;lo n&uacute;meros enteros positivos. Estas matrices asociativas
encierran sus &iacute;ndices o <I>claves</I> entre llaves (&iquest;os d&aacute;is
cuenta del sutil mnem&oacute;nico?). En esa l&iacute;nea, se le a&ntilde;ade
al componente de la matriz indexado por la fecha la pasta de la entrada
correspondiente. As&iacute;, hasta que se termina el fichero de entrada.
</p>

<P>Para imprimir el informe, tres cuartos de lo mismo que en el programa
anterior, salvo que en este caso, una matriz asociativa completa se indica
con <code>%</code>, en vez de la arroba.
</p>

<table class=ejercicio width=100% cellpadding=2 cellspacing=0 border=0>
    <tr><td bgcolor=green><table bgcolor=white cellspacing=0 cellpadding = 6><tr>
<td><ol>
<li> Leer un fichero con el formato  Primer_Apellido Segundo_Apellido, Nombre y escribirlo como   
<center>Nombre Primer_Apellido Segundo_Apellido</center></li>
<li> En el mismo fichero, presentar al final el número de veces que aparece cada apellido.  </li>
<li> Realizar un programa que, haciendo lo mismo que el manta.pl, lo
haga en la mitad de líneas. </li>
<li> Escribir un programa que haga lo mismo que la orden wc de UNIX,
es decir, para cualquier fichero, contar el número de líneas, de
palabras y de bytes, y presentarlo en 3 columnas con el nombre del
fichero en la cuarta. Hacer que funcione para varios ficheros,
introducidos en la línea de comandos.  </li>
<li> A partir del fichero de registro de visitas de un sitio Web, o
log, poner cuántasveces han consultado las páginas desde dominios de
primer y segundo orden, presentarlos por orden, con una opción que
permita seleccionar primer o segundo orden. </li>
<li> Realizar un programa que, a partir de una lista del tipo DNI
Apellidos, Nombre genere un fichero de password, con el formato 
<center>username:password:uid:gid:Nombre y Apellidos</center>
 Calcular el username con la inicial del nombre y el primer apellido;
si existe, usar el segundo apellido, y si existe también, añadir un
número de orden. Para el password, encriptar el DNI; el UID se genera
por orden alfabético a partir del número 1000, el gid es un entero
común, y el nombre y apellidos es elindicado. Al terminarlo, ofrecerlo
amablemente al administrador del sistema de tu Escuela o Facultad.</li></ol>

</td></tr></table></td></tr><caption><font
face="arial,helvetica">Ejercicios
<script>multicontador(3);</script></font></caption></table> 

<p><span class=v5>[v5]</span>A partir de la versión 5 de
<strong>perl</strong>, se pueden usar matrices bidimensionales,
mediante un mecanismo que se llama referencias; este mecanismo no nos
interesa ahora mismo, pero sí como podemos usarlo en nuestros
programas, tales como <a href=totales-v5.pl>el siguiente (totales-v5.pl)</a>:</p> 

<table class=listado align=center cellspacing=0 border=0 cellpadding=1><tr><td
bgcolor=black ><table width=100  cellspacing=0 border=0 cellpadding=1 ><tr><td bgcolor=white>
<pre><font size=+2>
1&nbsp;&nbsp;#<em>!/usr/bin/perl
</em>2&nbsp;&nbsp;<font color=green>$ARGV</font>[0] || <font color=blue><font color=red>die</font></font> "¡Dime el nombre del fichero de clientes, cohone!\n";
3&nbsp;&nbsp;<font color=blue>while</font>(&lt;&gt;) {
4&nbsp;&nbsp;  <font color=green>@linea</font> = <font color=red>split</font>;
5&nbsp;&nbsp;  <font color=green>@fecha</font>=<font color=red>split</font>(/\//,<font color=green>$linea</font>[$#<em>linea]);
</em>6&nbsp;&nbsp;  <font color=green>$pasta</font>=<font color=green>$linea</font>[$#<em>linea - 2];
</em>7&nbsp;&nbsp;  <font color=green>$totalDia</font>[<font color=green>$fecha</font>[1]][<font color=green>$fecha</font>[0]]+=<font color=green>$pasta</font>;
8&nbsp;&nbsp;}
9&nbsp;&nbsp;
10&nbsp;<font color=blue>for</font> ( <font color=green>$i</font> = 1; <font color=green>$i</font> &lt;= $#<em>totalDia; <font color=green>$i</font>++ ) {
</em>11&nbsp;  <font color=green>@dias</font> = @{<font color=green>$totalDia</font>[<font color=green>$i</font>]};
12&nbsp;  <font color=blue>for</font> ( <font color=green>$j</font> = 1; <font color=green>$j</font> &lt;= $#<em>dias; <font color=green>$j</font> ++ ) {
</em>13&nbsp;    <font color=red>print</font> "Trinque total del dia <font color=green>$j</font> del <font color=green>$i</font> = <font color=green>$totalDia</font>[<font color=green>$i</font>][<font color=green>$j</font>]\n" <font color=blue>if</font> <font color=green>$totalDia</font>[<font color=green>$i</font>][<font color=green>$j</font>];
14&nbsp;  }
15&nbsp;}
</font></pre>
</td></tr></table></td></tr><caption><font face="arial,helvetica">Listado <script>multicontador(1);</script>: Programa totales-v5.pl</font></caption></table>

<p>Este programa es bastante parecido al anterior, salvo que, en vez
de almacenarse los resultados en un array asociativo, se almacenan en
un array bidimensional; la primera dimensión es el mes, y la segunda
representa el día del mes. La línea 2 cambia simplemente para indicar
otra forma de detectar si hay un fichero en la línea de comandos o
imprimir un mensaje de error.</p>

<p>La línea 7 es la que usa una matriz bidimensional. Hasta aquí, todo 
normal; lo único relevante es que no hay que dimensionarla. Como
primer índice de la matriz se usa el elemento 1 de
<code>$linea</code>, es decir, el mes, y como segundo índice el primer 
elemento (el 0), es decir, el día.</p>

<p>Donde sí se nota un cambio es a partir de la línea 10; el bucle lo
hacemos sobre una matriz normal y corriente. El problema es que, tal
como sucede en las matrices bidimensionales en C, en
<strong>PERL</strong> las matrices bidimensionales son en realidad una 
matriz de matrices, o mejor una matriz de referencias. Por eso, en la
línea 11 lo que se hace es dereferenciar el elemento correspondiente y 
convertirlo en una matriz que podamos usar, la matriz
<code>@dias</code>. En la línea 13, usando interpolación, se imprimen
todos los elementos que son no nulos (<code>if
$totalDia[$i][$j]</code>) la mayoría serán nulos , y los dejamos sin imprimir.
<span class=v5>[/v5]</span>

<table class=ejercicio width=100% cellpadding=2 cellspacing=0 border=0>
    <tr><td bgcolor=green><table bgcolor=white cellspacing=0
cellpadding = 6 width=100%><tr>
<td><ol>
<li> Realizar un programa que lea un fichero organizado en filas y
columnas, tal como este <pre>
uno dos tres
cuatro cinco seis
siete ocho nueve
</pre>
y genere un documento HTML con los contenidos del fichero organizados
en una tabla; cada elemento del fichero deberá ir en una celda
diferente, así
<table border=1><tr><td>uno</td><td> dos</td><td> tres</td></tr>
<tr><td>cuatro</td><td> cinco</td><td> seis</td></tr>
<tr><td>siete</td><td> ocho</td><td> nueve</td></tr></table>
Aunque no es estrictamente necesario, usad una matriz bidimensional
para hacerlo.
</li>
</td></tr></table></td></tr><caption><font
face="arial,helvetica">Ejercicios
<script>multicontador(3);</script></font></caption></table> 



<TABLE  align=center cellpadding=5 bgcolor='darkseagreen'><tr><td>[<a href='tutoperl16.html'> Preguntas frecuentemente preguntadas</a>] [<a href='tutoperl17.html'> Bibliograf&iacute;a.</a>] [<a href='tutoperl18.html'> Recursos Internet</a>] [<a href='tutoperl8.html'> Purgando los pecados.</a>] </td></tr></table>

</BODY>
</HTML>
