6. ENTRADA Y SALIDA

6.1. STDIN, STDOUT y STDERR.

Perl necesita saber de dónde procede su información y a dónde debe enviarla. Estos canales con el mundo exterior se denominan manejadores de archivos (filehandles). Cuando se ejecuta Perl, su primer orden de actividad es asignar a los manejadores de los archivos los canales de comunicación para la entrada, la salida y la información sobre los errores. Estos tres manejadores de archivos, se crean automáticamente y tienen nombres reservados: STDIN, STDOUT y STDERR. STD significa estándar.

Los tres STD se usan con tanta frecuencia que Perl supone a menudo que existen y, por consiguiente, Perl no necesita que se mencionen explícitamente; en lugar de ello, Perl los crea y les asigna canales automáticamente.

Ejemplo:

Cuando ejecutamos Print "¡Maravilla!"; Perl supone que STDOUT es el monitor y por eso visualiza sin necesidad de indicar en ningún lugar STDOUT.

Print STDOUT "¡Maravilla!"; es igual que Print "¡Maravilla!";

Un ejemplo curioso con error (holaerr.pl):

# Forzamos un error omitiendo las comillas finales.

Print "Hola;

Produce el siguiente error: Can't find string terminator...line 3
(o algo similar según la versión de Perl que usemos).

Sabemos que con el simbolo > podemos redirigir una salida de pantalla a un archivo. Pero si tecleamos,

C:\>Perl holaerr.pl > error.txt

comprobaremos que error.txt no tiene nada, es decir, el error producido hace que Perl se detenga una vez que su mensaje aparece en pantalla (salida estándar). Después de esto no se hará nada más, ni siquiera el envio del mensaje a error.txt. Ahora hemos aprendido que la salida estándar de los errores STDERR es la pantalla.

6.2. Operadores de entrada < >.

Los símbolos <> representan la entrada o los operadores de lectura de Perl. Si STDIN se encuentra dentro de estos símbolos, el operador de lectura lee una línea cada vez desde ese manejador de archivo.

Ejemplo: $Nombre = <STDIN>;

Ejemplo (leearchi.pl):

#Al ejecutar este script, teclear unas palabras seguidas de enter y
#y repetir lo mismo una segunda vez. A medida que escribimos <STDIN>
#lee lo que tecleamos y al pulsar enter lo asigna a la variable $uno,
#Lo mismo ocurre le ocurre a $dos.

$uno = <STDIN>; #Lee una línea
$dos = <STDIN>; #Lee una más

print $uno.$dos; #Se concatenan las líneas usando un puntito.

Ejemplo de lectura controlando el flujo con While (leebucle.pl):

#While permite hacer un bucle para leer y escribir tantas líneas
#como queramos. La condición se escribe entre paréntensis y las
#líneas que hacen el bucle entre llaves. Para finalizar la entrada
#desde el teclado pulsar Control+Z.
#También es útil para leer archivos si lo usamos con el símbolo <
#como con C:\>Perl leebucle.pl <saludo.txt.

While (<STDIN>) {
print;
}

6.3. Lectura de un archivo de texto.

Veamos como se hace con un ejemplo que lee el archivo SALUDO.TXT (leeeste.pl):

#El archivo se abrirá con open y entre paréntesis indicaremos en
#primer lugar el nombre del FILEHANDLE (puede ser cualquiera pero en
#mayúsculas) y separado por una coma del nombre del archivo a leer.

# Abrir y leer el archivo SALUDO.TXT
open (FHANDLE, "SALUDO.TXT");
while (<FHANDLE>) {
print;
}

otra forma de hacerlo es:

open (FHANDLE, "SALUDO.TXT")
While ($linea, <FHANDLE>) {
print $linea;
}

6.4. Lectura de un archivo de texto usando @ARGV.

Un ejemplo que perfecciona lo anterior usando @ARGV (leeargu1.pl):

Perl lee argumentos de la línea de comandos y los pasa al script utilizando una variable de matrices especial llamada @ARGV.

Primero vamos a ver como se realiza está lectura de argumentos y luego mejoraremos el ejemplo anterior. El script siguiente lista los argumentos tecleados en la línea de comando.

# Lee argumentos de la línea de comando y los lista ordenadamente.

$NumArg = @ARGV; # NumArg almacena el número de argumentos
$Cuenta = 0;
while ($Cuenta < $NumArg) {
print "Argumento Núm. ", $Cuenta, " ---> ", $ARGV[$Cuenta], "\n";
$Cuenta++; # Incrementa en 1 la variable Cuenta
}

Para ejecutar teclear:

C:\>PERL leeargu1.pl Ya huele a Feria de Abril

Ejemplo (leeargu2.pl):

A continuación, vamos a realizar un script que lee de la línea de comandos dos argumentos: el primero es el nombre de un archivo y el segundo un modelo que usaremos para buscar y visualizar las ocurrencias encontradas en el archivo indicado.

$patron = $ARGV[1]; # $patron guarda el modelo o 2º argumento
open (FICHERO, $ARGV[0]); # Abre el archivo indicado como 1er. argum.
while (<FICHERO>) {
print if /$patron/;
}

Para probar teclear: C:\>PERL leeargu2.pl saludo.txt Adios

6.5. Lectura de un archivo con read().

La función read() lee un número de bytes de un archivo. Su sintaxis es:

read( FHANDLE, $Cadena, $LongitudALeer );

Ejemplo:

open (FHANDLE, "SALUDO.TXT");
$longitud = 30;
read (FHANDLE, $cadena, $longitud);
print $cadena, "\n";

6.6. Operaciones de entrada y salida en un archivo.

A continuación se muestra una lista con las operaciones de entrada y salida habituales para con los archivos.

Operación y Descripción

<STDIN>;
Lee una línea desde el teclado o un archivo redireccionado. $_ contiene la línea.

$linea = <STDIN>;
Lee una línea y la asigna a una variable escalar.

while (<STDIN>) {print;}
Lee y muestra líneas desde el teclado hasta pulsar Ctrl+Z o desde un archivo hasta encontrar el final del mismo.

while ($linea = <STDIN>)
Lee y asigna líneas a una variable escalar desde el teclado hasta pulsar Ctrl+Z o desde un archivo hasta encontrar el final del mismo.

while (<>) {print;}
Lee y muestra las líneas de una lista de nombres de archivos.

$archivo = $ARGV;
Si $ARGV es un nombre de archivo lo asigna a la variable escalar $archivo.

while (<"*.txt">) {print;}
Lee y muestra las líneas de todos los archivos con extensión .txt.

open(MANARC, "archivo.txt");
Abre archivo.txt y le asigna un manejador de archivo de nombre MANARC en modo lectura.

open(MANARC, "<archivo.txt");
Abre archivo.txt y le asigna un manejador de archivo de nombre MANARC en modo lectura.

open(MANARC,">archivo.txt");
Abre archivo.txt o lo crea si no existe en modo escritura.

open(MANARC,">>archivo.txt");
Abre archivo.txt o lo crea si no existe en modo escritura-adición.

$linea = <MANARC>;
Lee una línea de un archivo ya abierto.

@linea = <MANARC>;
Lee todas las líneas de un archivo y las almacena en la matriz @linea.

@linea = <>;
Lee todas las líneas de una lista de archivos dados como argumentos.

open(MANARC, "arc.txt") || die("Problemas para abrir");
Abre archivo.txt y le asigna un manejador de archivo de nombre MANARC en modo lectura. Si el archivo no existe u ocurre otro problema detiene el programa y muestra el mensaje "Problemas para abrir".

6.7. Operaciones avanzadas con archivos.

Operación y descripción

open(MANARC, "+>arc.txt");
Abre un archivo en modo lectura/escritura. Si el archivo no existe se creará.

open(MANARC, "+<arc.txt");
Abre un archivo en modo lectura/escritura. Si el archivo no existe dará error.

read(MANARC, $Datos, $Long);
Lee una cadena con la longitud de $Long desde la posición actual en un archivo abierto y la almacena en la variable $Datos.

seek(MANARC, $Posic, 0);
Coloca el puntero en el número de byte que indique $Posic contando desde el inicio. $Posic debe ser positivo o cero.

seek(MANARC, $Posic, 1);
Mueve el puntero el número de bytes que indique $Posic desde la posición actual.

seek(MANARC, $Posic, 2);
Coloca el puntero en el número de byte que indique $Posic contando desde el final. $Posic debe ser negativo o cero.

read(MANARC, $Dat, $L1,$L2);
Lee una cadena con la longitud de $L1 desde la posición actual en un archivo abierto y la almacena en la variable $Dat, pero teniendo en cuenta que $Dat ya tenía otra cadena de la cual se respeta los $L2 caracteres iniciales.

$PosicionActual = tell(MANARC);
Devuelve la posición actual del puntero.

6.8. Imprimir datos con sprintf().

Sprintf() a aplica formato a datos.

Sintaxis: Sprintf(plantilla, $expresión)

Ejemplos (sprintf.pl):

# Aplicando formato a datos con sprintf() y la plantilla %s (espacios).

$lenguaje = "Perl";
$longitud = 10;
$conformato = sprintf("%s", $lenguaje);
print $conformato,"\n"; # Imprime:Perl
$conformato = sprintf(">>%s<<", $lenguaje);
print $conformato,"\n"; # Imprine:>>Perl<<
$conformato = sprintf(">>%s <<", $lenguaje);
print $conformato,"\n"; # Imprime:>>Perl <<
$conformato = sprintf(">>%10s<<", $lenguaje);
print $conformato,"\n"; # Imprime:>> Perl<<
$conformato = sprintf(">>%-10s<<", $lenguaje);
print $conformato,"\n"; # Imprime:>>Perl <<
$conformato = sprintf(">>%-${longitud}s<<", $lenguaje);
print $conformato,"\n"; # Imprime:>>Perl <<

6.9. Imprimir datos con printf().

Printf() a diferencia de print cuando escribe datos lo hace aplicando un formato de la misma que sprintf().

Sintaxis: printf(plantilla, argumento1, argumento2, argumenton)

Plantilla - Descripción
%c - Carácter
%d - Número entero
%e - Punto flotante en notación científica
%f - Punto flotante en notación decimal
%g - Punto flotante en notación %e y %f
%s - Cadena
%x - Entero con formato hexadecimal (minúsculas)
%X - Entero con formato hexadecimal (mayúsculas)

6.10. Imprimir bloques de datos con print<<.

Print<< permite imprimir bloques de texto.

Sintaxis: print <<etiqueta;
Línea texto1;
Línea texto2;
Línea texton;
Etiqueta

Ejemplo (printet.pl):

print <<BLOQUE
<HTML>
<HEAD><TITLE>Titulo</TITLE></HEAD>
<BODY>Contenido de la web</BODY>
</HTML>
BLOQUE

6.11. Ejemplo con ficheros de datos.

Ejemplo (config.pl): Config.pl lee el archivo de configuración Programa.ini y lo válida. El contenido de Programa.ini es:

TipoInstalación=red
UnidadInstalación=C:
DirectorioInstalación=\PAQUETES\APLICACIONES\
ArchivoEjecutable=PROGRAMA.EXE
NúmeroUsuarios=3
ArchivoConfiguración=config.ini

Si la información es correcta crea el archivo config.ini.

open (FHANDLE,"PROGRAMA.INI") ||
Die ("Error: No existe el archivo programa.ini");
@Tabla = ();
while (<FHANDLE>) {
print $_;
s/\n//g;
@ParteCadena = split(/=/,$_);
push(@Tabla, $ParteCadena[0]);
push(@Tabla, $ParteCadena[1]);
}
close(FHANDLE);
%TablaAsoc = @Tabla;
$TI = $TablaAsoc{"TipoInstalación"};
$UI = $TablaAsoc{"UnidadInstalación"};
$DI = $TablaAsoc{"DirectorioInstalación"};
$AE = $TablaAsoc{"ArchivoEjecutable"};
$NU = $TablaAsoc{"NúmeroUsuarios"};
$AC = $TablaAsoc{"ArchivoConfiguración"};
print "\n";
$error = &ValTI($TI);
$error = &ValUI($UI);
$error = &ValDI($DI);
if ($error == 1) {
print "Error: programa.ini no es válido\n";
} else {
print "programa.ini es válido\n";
print $UI.$DI.$AE;
open(ARCHIVO, ">$AC") || die("No ha sido posible la creación de ".$AC);
print ARCHIVO "[Instalación]\n";
print ARCHIVO "AplicaciónInstaladaEn=".$UI.$DI.$AE."\n";
print ARCHIVO "UsuariosAplicación=".$NU."\n";
close(ARCHIVO);
}

# Funciones de usuario

sub ValTI{
if ($_[0]=~/^red|^mono/) {
print "Tipo Instalación Correcta ->".$_[0]."\n";
return 0;
} else {
print "Tipo Instalación Incorrecta ->".$_[0]."\n";
return 1;
}
}

sub ValUI{
if ($_[0]=~/^[a-zA-Z][:]/) {
print "Unidad Instalación Correcta ->".$_[0]."\n";
return 0;
} else {
print "Unidad Instalación Incorrecta ->".$_[0]."\n";
return 1;
}
}

../continúa/..
sub ValDI{
if ($_[0]=~/^\\.*/) {
print "Directorio Instalación Correcta ->".$_[0]."\n";
return 0;
} else {
print "Directorio Instalación Incorrecta ->".$_[0]."\n";
return 1;
}
}