You are on page 1of 162

Programacinyautomatizacin.

Recursosdeladministradordesitios

HugoMazaM.

Manualde

Perlbsico
desdecero
Conejemplossencillospara
automatizacindeprocesos
ytareasenservidores
Edicin0.1

Licenciadeuso
EstaobrahasidoliberadabajolaproteccindelaLicenciadeusoCreativeCommons

AtribucinNocomercialLicenciamientoRecproco2.5Mxico
Ustedeslibrede:
copiar,distribuirycomunicarpblicamentelaobra

hacerobrasderivadas
Bajolascondicionessiguientes:

AtribucinDebesreconocerlaautoradelaobraenlostrminos
especificadosporelpropioautorolicenciante.

NocomercialNopuedesutilizarestaobraparafinescomerciales.
LicenciamientoRecprocoSialteras,transformasocreasunaobraapartir
deestaobra,solopodrsdistribuirlaobraresultantebajounalicenciaigual
asta.
RegistroIndautor.Mxico.

HugoMazaM.Perlbsicodesdecero

Pag.4

Conejemplossencillosparaautomatizacindetareasenservidores

ndice
DedicatoriayAgradecimientos..........................................................................................11
Prlogo..............................................................................................................................*pte
CAPTULO1.Introduccin
1.1QuesPerl?..................................................................................................................15
1.2Eldromedario..................................................................................................................16
1.3Caractersticas.................................................................................................................16
1.4Cosasimportantesparacomenzar.................................................................................17
1.5Cosastilesalcomenzar................................................................................................18
CAPTULO2.ElscriptdePerl
2.1NuestroprimerscriptdePerl...........................................................................................21
CAPTULO3.Representacindelosdiferentestiposdedatos
3.1LosEscalares..................................................................................................................25
3.1.1Nmerosrealesyenteros.............................................................................................26
3.1.2Cadenasdecaracteres.................................................................................................27
3.1.2.1Interpolacindevariables........................................................................................27
3.1.2.2Concatenacindevariables.....................................................................................29
3.1.3Boleanos.......................................................................................................................30
3.1.4Contextodeusodelasvariables..................................................................................31
3.2Losarraysolistasindexadas..........................................................................................32
3.3Loshashes,oarraysdeindexacinliteral,olistasasociativas.......................................35
3.4Lasreferencias................................................................................................................37
3.4.1Arrayreferenciadoannimo.........................................................................................38
3.4.2Hashreferenciadoannimo.........................................................................................39
3.5Arraysbidimensionales...................................................................................................40
3.6Arraysbidimensionalesreferenciadosannimos............................................................42
3.7Hashesmultidimensionales............................................................................................43
3.8Hashesmultidimensionalesreferenciadosannimos.....................................................44
CAPTULO4.OperadoresenPerl
4.1Operadoresparaescalares.............................................................................................47
4.1.1Operadoresaritmticos.................................................................................................47
4.1.2Operadoresrelacionales...............................................................................................49
4.1.3Operadoreslgicosobooleanos..................................................................................51
4.1.4Operadoresdeseleccin..............................................................................................52
Pag.5

HugoMazaM.Perlbsicodesdecero

4.1.5Operadoresdeasignacin............................................................................................53
4.1.5.1Operadordeasignacin=........................................................................................53
4.1.5.2Operadordeasignacin+=.....................................................................................53
4.1.5.3Operadordeasignacin=......................................................................................53
4.1.5.4Operadordeasignacin*=......................................................................................53
4.1.5.5Operadordeasignacin/=......................................................................................54
4.1.5.6Operadordeasignacin.=......................................................................................54
4.1.6Funcionesdefinidasparamanejodecadenasdecaracteres.......................................55
length,chop,chomp,index,rindex,substr,uc,lc,funcionesnumricas
4.2FuncionesparaArrays....................................................................................................59
4.2.1Funcinpush................................................................................................................59
4.2.2Funcinpop..................................................................................................................59
4.2.3Funcinshift.................................................................................................................60
4.2.4Funcinunshift.............................................................................................................60
4.2.5Funcinsplit.................................................................................................................60
4.2.6Funcinjoin..................................................................................................................61
4.2.7Funcinsort.................................................................................................................62
4.2.8Funcinreverse............................................................................................................62
4.2.9Funcin$#....................................................................................................................63
4.2.10Funcinmap...............................................................................................................64
4.2.11Funcingrep...............................................................................................................64
4.3FuncionesparaHashes..................................................................................................65
4.3.1Funcinkeys.................................................................................................................65
4.3.2Funcinvalues.............................................................................................................65
4.3.3Funcindelete..............................................................................................................66
4.3.4Funcineach................................................................................................................66
CAPTULO5.Estructurasdecontrol
5.1Lafuncinif.....................................................................................................................71
5.1.1Else...............................................................................................................................74
5.1.2Elsif...............................................................................................................................75
5.1.3Sintaxiscasireal...........................................................................................................76
5.2Lafuncinunless............................................................................................................76
5.3Lafuncinwhile..............................................................................................................77
5.4Lafuncinfor..................................................................................................................80
5.5Lafuncinforeach...........................................................................................................81
5.6Lafuncinuntil................................................................................................................81
5.7Bifurcacionesparalosbucles.........................................................................................82
5.7.1Lasalidalast.................................................................................................................82
5.7.2Lafuncinnext.............................................................................................................83
Pag.6

Conejemplossencillosparaautomatizacindetareasenservidores

5.7.3Etiquetas.......................................................................................................................84
CAPTULO6.Expresionesregulares
6.1Expresionesregularesdecomparacin..........................................................................89
6.1.1Memoriadelasexpresiones.........................................................................................95
6.2Expresionesregularesdesustitucin..............................................................................99
CAPTULO7.Funcionespropias,subrutinas
7.1Lavariableespecial@_................................................................................................104
7.2Argumentosdeunafuncinpropiaosubrutina.............................................................105
7.3Variablesglobalesylocales...........................................................................................105
7.4Captandolosargumentos..............................................................................................107
7.5Retornandolosresultados.............................................................................................109
7.6Uniendotodo.................................................................................................................109
7.7Variablessemilocales.....................................................................................................111
7.7.1Reutilizacindecdigo................................................................................................112
CAPTULO8.Entrada/SalidaenPerl.Archivos
8.1Manejadoresdeentrada/salidadedatos(I/OFilehandle)..............................................117
8.2Laentradaylasalidaestandard....................................................................................117
8.3AbrirycerrararchivosenPerl.......................................................................................118
8.4Elaccesoaarchivos......................................................................................................119
8.5ManejodeerroresparaI/Odearchivos........................................................................120
8.5.1Algunosmtodossimples...........................................................................................120
8.5.2Lasalidadie...............................................................................................................120
8.5.3Eloperadororyeloperador||....................................................................................121
8.5.4Diferentessalidas.......................................................................................................121
8.6Laseguridadenelmanejodearchivos.........................................................................123
8.6.1FileTest,operadoresdecomprobacindearchivos..................................................123
8.6.2Bloqueodearchivos...................................................................................................125
8.6.2.1Muybreveintroduccinalusodemdulos..............................................................126
8.6.2.2UsodeflockdelmduloFcntl.................................................................................127
8.6.3MtodoMazadeseguridad(delautor).......................................................................128
8.7Manipulacindearchivosydirectorios..........................................................................131
8.7.1Removiendounarchivo...............................................................................................131
8.7.2Renombrandounarchivo............................................................................................132
8.7.3Creandoyremoviendodirectorios..............................................................................132
8.7.4Permisos.....................................................................................................................132
8.8Otrosmodosdeacceso................................................................................................132
8.8.1LoscanalesPIPEsdecomunicacin..........................................................................133
Pag.7

HugoMazaM.Perlbsicodesdecero

CAPTULO9.Desarrollodescripts
9.1Elpragmastrict..............................................................................................................138
9.2Objetosdelosmdulos.................................................................................................138
9.3AlgunosEjemplosprcticos..........................................................................................139
9.3.1Ejercicio1:..................................................................................................................140
Extraerlafechadelsistemaparamanejarlaenunscript
9.3.2Ejercicio2:..................................................................................................................142
Monitorizareltamaodearchivoslogparaquenocrezcamasdeltamaopermitido
9.3.3Ejercicio3:..................................................................................................................145
Monitorizarelnmerodelneasdearchivoslogparaquenocrezcamas
delnmeropermitido
9.3.4Ejercicio4:..................................................................................................................147
MonitorizacindeFilesystems
9.3.4.1Ejecucindelscriptvacrontab.............................................................................151
9.3.5Ejercicio5:..................................................................................................................154
PrcticasconelusodemdulosadicionalesdePerl
9.3.6Ejercicio6:..................................................................................................................156
Ordenamientoporcamposdeunamatriz(AlgoritmodeMaza)
Crditos..............................................................................................................................161

Pag.8

Conejemplossencillosparaautomatizacindetareasenservidores

Pag.9

HugoMazaM.Perlbsicodesdecero

Pag.10

Conejemplossencillosparaautomatizacindetareasenservidores

DedicatoriayAgradecimientos
Unpocodehistoriaanticlnica...
Todoestocomenzconunainiciativaintragrupaldeenseanza,lacualconstabaenquecadamiembrodel
equipodetrabajocapacitaraalosdemsenloqueerabuenoensurea.
Porrazonesalgoobvias,fuiyoelprimerodelalistaparacompartirunpocomisescasosconocimientosdePerl
conmiscompaeros;conocimientosquemehabanllevadoatenerunreconocimientoentrelosmismosporlos
resultadosdemitrabajo.
Laideanacedecrearunmanualpequeoparaapoyodelcurso,sinembargoconeltiempolefuiagregandomas
cosas,masdetalles,tareasy,repentinamentemedicuentadequeelmaterialnoeraimprimibleenlaempresa,
porqueyanoeranunascuantashojas.
Estocondujoanotomarencuentalaimpresinyatomarencuentaalgunoscomentariosdehacerlomaslegible
enunaPC.
Deestaforma,mevimotivadoparacolocarlecoloralcdigo,delamismaformaenqueyoloveaenmieditorde
lalaptop.
Enunmomento,lasfrgilesnotasparaelcurso,setornaronenunmanualformalencolor,queeramasfcilde
asimilarparalagentequenoestabaacostumbradaaleercdigo.
As,estemanualestconsideradoparaaquellaspersonasquehantenidomuyescasocontactoconelmundode
laprogramacin(onulo)yquedeseanllegaracrearprocesosdeautomatizacindetareasodeanlisisde
informacin,alterminardeleerelpresente.
Estambintilcomomanualdebolsillopararecordarloqueenocasionessenosolvidasinraznalguna,es
comodecimosenMxicocuandojvenes,un"acorden".

As,pongoaladisposicindetodoslosquedeseaningresaralinteresantemundodelaprogramacindePerl,
estediminutomanualqueesperoseamuytilcomoelprimerpasoenelaprendizajeyusoformaldePerl.As
mismo,paralosinstructoresdenivelbsicodePerl.
Hedereconocerquesinlainsistenciayelapoyodemisexcompaerosdetrabajoeneseentoncesdelaempresa
dondeprestomisservicios,nohubierapodidorealizarestepequeoperointeresantelibrillodePerl.
MisagradecimientosaellosporelintersenaprendersobrePerl.
Igualmentemanifiestoengranmedidamisagradecimientosatodasaquellaspersonasquedealgunauotraforma
seinteresaronpormiesfuerzoeneldesarrollodelpresentedocumentoyquemesirvieronparaseguiradelante
conl.
YmuyespecialmenteamimujerMayequesoportalejarmedelastareasdomsticasalgunosfinesdesemana.

Atodosellosyaustedqueloestleyendo...Gracias.

Pag.11

HugoMazaM.Perlbsicodesdecero

Pag.12

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO1

Introduccin
Pag.13

HugoMazaM.Perlbsicodesdecero

Pag.14

Conejemplossencillosparaautomatizacindetareasenservidores

1.Introduccin
1.1QuesPerl?
PerlesunlenguajedeprogramacindiseadoporLarryWallcreadoen1987.Perltoma
caractersticasdelC,dellenguajeinterpretadoshell(sh),AWK,sed,Lispy,enungrado
inferior,demuchosotroslenguajesdeprogramacin.
Estructuralmente,PerlestbasadoenunestilodebloquescomolosdelCoAWK,yfue
ampliamenteadoptadoporsudestrezaenelprocesadodetextoynotenerningunadelas
limitacionesdelosotroslenguajesdescript.
LarryWallcomenzatrabajarenPerlen1987mientrastrabajabacomoprogramadoren
Unisysyanuncilaversin1.0enelgrupodenoticiascomp.sources.miscel18de
diciembredeesemismoao.
Perlsellamoriginalmente"Pearl",porlaParboladelaPerla.LarryWallqueradarleal
lenguajeunnombrecortoconconnotacionespositivas;aseguraquemir(yrechaz)todas
lascombinacionesdetresycuatroletrasdeldiccionario.Tambinconsidernombrarlo
comosuesposaGloria.Walldescubriantesdellanzamientooficialqueyaexistaun
lenguajedeprogramacinllamadoPEARLycambilaortografadelnombre.
Elnombrenormalmentecomienzaconmayscula(Perl)cuandoserefiereallenguajeycon
minsculas(perl)cuandoserefierealpropioprogramaintrpretedebidoaquelossistemas
deficherosUnixdistinguenmaysculasyminsculas.Antesdellanzamientodelaprimera
edicindeProgrammingPerleracomnreferirseallenguajecomoperl;RandalL.
Schwartz,sinembargo,forzelnombreenmaysculaenellibroparaquedestacaramejor
cuandofueraimpreso.Ladistincinfuesubsiguientementeadoptadaporlacomunidad.
Elnombreesdescritoocasionalmentecomo"PERL"(porPracticalExtractionandReport
LanguageLenguajePrcticoparalaExtraccineInforme).Aunqueestaexpansinha
prevalecidoenmuchosmanualesactuales,incluyendolapginademanualdePerl,esun
retroacrnimoyoficialmenteelnombrenoquieredecirnada.LaortografadePERLen
maysculasesporesousadacomojergaparadetectaraindividuosajenosalacomunidad.
Sinembargo,sehansugeridovariosretroacrnimos,incluyendoelcmicoPathologically
EclecticRubbishLister(ContabilizadordeBasuraPatolgicamenteEclctico).

Pag.15

HugoMazaM.Perlbsicodesdecero

1.2Eldromedario
Perlsesimbolizageneralmenteporundromedario(camello
arbigo),quefuelaimagenelegidaporeleditorO'Reillyparala
cubiertadeProgrammingPerl,queporconsiguienteadquiriel
nombredeElLibrodelDromedario.O'Reillyespropietariodeeste
smbolocomomarcaregistrada,perodicequeusasusderechos
legalessloparaprotegerla"integridadeimpactodeeste
smbolo".O'Reillypermiteelusonocomercialdelsmbolo,yofrece
logosProgrammingRepublicofPerlybotonesPoweredbyPerl.
1.3Caractersticas
LapginademanualdeUnixperlintrodice:
Perlesunlenguajedepropsitogeneraloriginalmentedesarrolladoparala
manipulacindetextoyqueahoraesutilizadoparaunampliorangodetareas
incluyendoadministracindesistemas,desarrolloweb,programacinenred,
desarrollodeGUIyms.
Sepreviquefueraprctico(facilidaddeuso,eficiente,completo)enlugarde
hermoso(pequeo,elegante,mnimo).Susprincipalescaractersticassonquees
fcildeusar,soportatantolaprogramacinestructuradacomolaprogramacin
orientadaaobjetosylaprogramacinfuncional,tieneincorporadounpoderoso
sistemadeprocesamientodetextoyunaenormecoleccindemdulos
disponibles.
EldiseodePerlpuedeserentendidocomounarespuestaatresampliastendenciasdela
industriainformtica:
1. Rebajadeloscostesenelhardware
2. Aumentodeloscosteslaborales
3. Mejorasenlatecnologadecompiladores.
Hayunampliosentidodeloprctico,tantoenellenguajePerlcomoenlacomunidadyla
culturaquelorodean.ElprefaciodeProgrammingPerlcomienzacon,"Perlesunlenguaje
paratenertutrabajoterminado".UnaconsecuenciadeestoesquePerlnoesunlenguaje
ordenado.Incluyecaractersticassilagentelasusa,toleraexcepcionesalasreglasy
emplealaheursticapararesolverambigedadessintcticas.Debidoalanaturaleza
Pag.16

Conejemplossencillosparaautomatizacindetareasenservidores

indulgentedelcompilador,avecesloserrorespuedenserdifcilesdeencontrar.Hablando
delvariadocomportamientodelasfuncionesinternasenloscontextosdelistayescalar,la
pginademanualdeperlfunc(1)dice"Engeneral,hacenloquetuquieras,siempreque
quieraslacoherencia."
Perlestimplementadocomounintrprete,escritoenC,juntoconunagrancoleccinde
mdulos,escritosenPerlyC.Ladistribucinfuentetiene,en2005,12MBcuandose
empaquetaycomprimeenunficherotar.Elintrpretetiene150.000lneasdecdigoCyse
compilaenunejecutablede1MBenlasarquitecturasdehardwaremstpicas.Deforma
alternativa,elintrpretepuedesercompiladocomounabibliotecayserembebidaenotros
programas.Haycercade500mdulosenladistribucin,sumando200.000lneasdePerly
unas350.000lneasadicionalesdecdigoC.MuchodelcdigoCenlosmdulosconsiste
entablasdecodificacindecaracteres.
(delpunto1.1al1.3,informacinextradadewikipedia)
1.4Cosasimportantesparacomenzar
Perlesunlenguajeinterpretado,esdecir,paraejecutarunscriptdePerldebemosindicarle
alsistemaoperativoelintrpretequequeremosutilizarparaejecutarlo.
Haydosmanerasdehacerlo:
a)EjecutandoelbinariodePerlypasarlecomoargumentoelnombrecompletodel
archivodePerl.Ejemplo(enlneadecomandosdeUnix):
user@host ~$ perl script.pl

b)Insertandoenlaprimeralneadelarchivodelscript,loscaracteresclsicosde
iniciodealgnscriptquereconoceelsistemaoperativo,elcaracterdesharpyel
signodeadmiracin(#!),seguidodelarutadelbinariodePerl.Algocomoesto:
#!/usr/bin/perl
....y comienza el script

Enelsegundocasodeberemostenerelarchivoconpermisosdeejecucin,esdecir,755
rwxrxrx.
EstoaplicaparaservidoresconsistemasoperativosbasadosenelestandardPOSIX,ya
queenalgunossistemasoperativosquenotienencontroldepermisosdearchivos,como
Windows,noesnecesariobuscarlaformadehacerloejecutable,yaqueahtodoslos
archivosloson.
Pag.17

HugoMazaM.Perlbsicodesdecero

1.5Cosastilesalcomenzar
Perlvienepordefectoinstaladoentodas(desconozcosialgunano)lasversionesdeUnix,y
lossistemasoperativosUnixLikecomoGNU/Linux.
Yexistenversionesinstalablesparacasitodoslossistemasoperativos.
SisabesquetienesinstaladoPerl,haymaneradesaberalgosobrelenlneade
comandos:
perlv:MuestralaversindelintrpretedePerlqueestamosutilizando.
perlV:Muestrainformacinsobrelaconfiguracindelintrpretedeperl.
Otrascuriosidadesdelneadecomando:
perldscript:Ejecutaelscriptbajoeldepurador.
perlwscript:Daavisossobrelasconstruccionesconerrores.
perlxscript:Empiezaainterpretarelarchivoquecontieneelscriptcuando
encuentralareferenciaalintrprete,porejemplo:#!/usr/bin/perl.

Pag.18

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO2

ElscriptdePerl
Pag.19

HugoMazaM.Perlbsicodesdecero

Pag.20

Conejemplossencillosparaautomatizacindetareasenservidores

2.ElscriptdePerl
UnscriptenPerlesunasucesindeinstrucciones.
Cadainstruccinsoladebeterminarsiempreconunapuntoycoma(;).
Cuandodeseamosinsertarcomentariosenlosscripts,estosdebenirprecedidosporel
smbolodesharp(#).Todosloscaracteresquesiguenaestesmboloyqueestn
contenidosenlamismalneaseconsiderancomentariosyseignoranparalaejecucindel
programa.
Comoconvencin,seusanterminacionesparalosscriptsdePerlcaractersticas,comopor
ejemplo:.pl.cgi.Aunquesepuedeusarcasicualquierterminacinquedeseemoso
inclusoninguna,cuandoseanecesario.Paraserordenados,usaremosestaconvencin
estandard.
2.1NuestroprimerscriptdePerl
UniversalmentefamososehahecholaimpresindelHolamundoalmostrarelprimer
scriptdecualquierlenguaje,quenolopodemosdejardeladoenestahumildeobra.
Abrimosnuestroeditordetextopreferidoenelequipodeprcticasyempezamosaescribir
elcdigoenPerl,elcualesmassencillodeloqueparece.
Alrespectopodemosrecomendarelusodealgunosprogramaspotentesparaescribir
cdigo:
EnGNU/LinuxesmuybuenoelprogramaGeany(http://www.geany.org/)elcuales
sumamenteamigablepararemarcarlasintaxisdemuchoslenguajes,obienBluefishde
OpenOffice(http://bluefish.openoffice.nl/).
SibienGeanyesmaspoderosoenelcontroldelasintaxis,Bluefishposeeunclientede
FTPparasubiralservidorlosarchivosrecinmodificadossinusarotroprogramacomo
Filezilla(http://filezillaproject.org/)porejemplo.
EnWindowspuedesusarNotpad++(http://notepadplus.sourceforge.net/es/site.htm).
TambinexisteFilezillaversinparaestesistemaoperativo.
Comenzamoscomohabamoscomentado,conlainformacinparaelsistemaoperativo,
seguidadenuestraprimeraexperienciaconPerl,laimpresindeunacadena:
Pag.21

HugoMazaM.Perlbsicodesdecero
#!/usr/bin/perl
print "Hola mundo! \n";
# Este es un comentario

Puntosimportantesqueaprenderdeesteprimerscript:
Enestecasovemosclaramentequepodemosexternarlainformacinalapantalla
mediantelafuncinprint,lacualredirigelasalidaaunmanejadorespecialqueeneste
casosinoespecificamosuno,eslasalidaestandardoterminal;lapantalladenuestro
monitor.
Posteriormenteveremosestetemapocoapoco.
Podemosvertambinquelainformacinquequeremosimprimirestcolocadaentre
comillasdobles.
Elsaltodelnea,lovemoscomnmentereflejadocomo\n,diagonalinversaylaletran.
Yesuncaractermas,peroesuncaracterespecial.
As,podemosposicionarelcursorenotrorenglndespusdeterminardeejecutarelscript.
Duranteeltranscursodellibrousaremosestanotacinparaalgunoscaracteresespeciales
comoeselcasodelusadoenesteprimerscript,saltodelnea.
Masadelanteentenderemosdequesetrata.
Unavezquehayamosverificadolospermisosdedichoscriptestaremoslistospara
ejecutarlosimplementetecleandoenlalneadecomandos:
user@host ~$ ./hola.pl

Obien:
user@host ~$ perl hola.pl

Pag.22

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO3

Representacindelos
diferentestiposdedatos
Pag.23

HugoMazaM.Perlbsicodesdecero

Pag.24

Conejemplossencillosparaautomatizacindetareasenservidores

3. Representacindelosdiferentestiposdedatos
EllenguajePerlposeetrestiposderepresentacionesdedatos:
1. Escalares.
2. Arraysolistasindexadas.
3. Hashesoarraysdeindexacinliteral,olistasdeasociacin.
Deahoraenadelante,llamaremosvariableatodarepresentacindedatos.
Losdatosrepresentadosdentrodelasvariablesescalaressonlascadenas.
Losdatoscontenidosenlosarraysoenloshashes,generalmentepuedencontener
variablesescalares.
Estastresrepresentacionespermitenasociaracadavariableutilizadauntipodecadena.
EsmuyimportantecomentarqueenPerl,nilasvariablesnilostiposdedatosdentrodelas
variablestienenquedeclararseantesdeiniciarlaconstruccindelprograma.
Lasvariablessepuedendeclarardemaneradinmicaconformevatranscurriendo
elprogramayposeenunvalorpredeterminadoenfuncindelcontexto.
Osea,quelaspodemosdeclararencualquiermomentoencuantolasnecesitemos.
Estonosdaunalibertadcompletaconelusodevariablesencomparacinconotros
lenguajesdeprogramacincomoporejemplojava.
3.1LosEscalares
ElescalarrepresentaeltipodedatosbsicoenPerl.Ynospermiterepresentarnmeros
reales,nmerosenterosycadenasdecaracteres.
Perlpermiterepresentarlosdatosconlosquetrabajamosdeunamaneramuyfcily
directa.
Unacadenasimpleesrepresentada,comoenotroslenguajes,conunsmbolodepesos($)
seguidadelnombredelacadena,lacualadmiteensunombreloscaracteressimples
Pag.25

HugoMazaM.Perlbsicodesdecero

alfanumricosyelcarcterunderscore(_)oguinbajo,ynodebecomenzarconnmero.
Ejemplosdenombresdevariablesescalaresquepodemosusar:
$nombre_usuario;
$nombreUsuario;
$salida_calculo;
$resultadoTotal;
$resTotal;
$subTotal1;
$subTotal_2;

# caracteres alfanumricos y underscore

3.1.1Nmerosrealesyenteros
Losvaloresnumricosexpresadosliteralmentesepresentanenformadevaloresreales
codificadosendobleprecisin.Aspues,Perlnodistingueentreenterosyflotantes.
Esteformatointernoseutilizaparatodaslasoperacionesaritmticas.
Yaunqueenotroslenguajesdeprogramacin,nmerosycadenasdecaracteressondos
cosasmuydistintas,enPerlambossonescalares.
As,esposibledeclararunacadenanumricaingresndoladentrodecomillasdobleso
sencillasytrabajarconellacomonmero,aunquesinposeerprecisinreal.
Ejemplosdedatosnumricos:
$x
$y
$n
$i

=
=
=
=

0.789;
1.22e-22;
765;
-128;

#
#
#
#

es
es
es
es

un
un
un
un

real
real
entero
entero

Hayquehacernotarenestosejemplosdoscosas:
Usamoselsignodepesos($)paradeclararlaexistenciadeunavariable.
Losdatosovaloresnumricossonasignadosalasvariablesdirectamentesinusar
comillasparaelefecto,estosedebeasuvalornumrico.Lascadenas,como
veremosmasadelante,debenusarotrosmtodosparaserdeclarados.
Losvaloresenterosnopuedenempezarconceroporqueestoespecificaunentero
mediantesucodificacinoctal.Valoresoctalescomienzanconcero0;losvalores
Pag.26

Conejemplossencillosparaautomatizacindetareasenservidores

hexadecimalescomienzanconun0x,ycon0blosbinarios.Porejemplo:
$x = 0377;
$y = 0xff;
$y = 0b11111111;

# equivale a 255 (representacin octal)


# equivale a 255 (representacin hexadecimal)
# equivale a 255 (representacin binaria)

3.1.2Cadenasdecaracteres
Lascadenasdecaracteresseespecificanpormediodeunasucesindecaracteres
delimitadaporcomillasdobles("..")ocomillassimples('..').
EstasdosrepresentacionessoninterpretadasporPerlenmuydistintaforma.
Cuandovandelimitadasporcomillasdobles(".."),todavariablereferidaenelinteriorde
lacadenaseevalayesreemplazadaporsuvalor.EstosellamaInterpolacinde
variables.
3.1.2.1Interpolacindevariables.
Veamosunejemplo,enlasinstruccionessiguientes,lavariable$wldesremplazadaporla
cadenadecaracteres"mundo"enelinteriordelavariable$str.
$wld = "mundo";
$str = "Hola $wld!"; # se sustituye la variable $wld por su valor
print $str , "\n";
# imprime Hola mundo!, adems de un salto de lnea

Porelcontrario,enlascadenasdecaracteresdelimitadasporcomillassimples,todoslos
caracterespermanecenintactos.Porejemplo:
$wld = "mundo";
$str = 'Hola $wld!'; # no se sustituye la variable $wld
print $str , "\n";
# imprime Hola $wld!

Lacadena$wldnuncaesremplazadaporelvalordeestavariable.ImprimeHola$wld!.
As,sideseamosqueunaeminentesustitucindecadena(interpolacin)nosellevea
cabo,debemosutilizarlascomillassimplesparacrearelvalordelacadenasinla
interpolacin.
Estoaplicatambincuandoincluyamoscaracteresespecialesdentrodelacadena,muchos
losveremosmasadelante.
Pag.27

HugoMazaM.Perlbsicodesdecero

Hayocasionesquenecesitamosusarcomillasdoblesparadeclararunacadenaporlas
variablesinternasquellevadentrodesta,pero(siemprehayunpero)tambindentrodela
mismacadenaprincipaldebemosusarcomillasdobleporalgunarazn.
Enestecaso,podemoshacerusodelcaracterespecialbackslashodiagonalinversa(\)
seguidodelascomillasdobles.Ladiagonalinversa,nospermitedeclararelvalorverdadero
delsiguientecaractersinhacerusodeloquepuedasignificarparaPerl.
EnestecasolascomillasdoblessignificaranparaPerlunfinaldecadena,perosidentro
delacadenainsertamosun(\"),PerlNOlointerpretarcomofinaldecadena,sinocomo
uncaractermasdentrodelacadena:
$miCadena = "Hola \"mundo\".\n";
print $miCadena;

# esto imprime: Hola "mundo". y un salto de lnea


# para que el prompt del sistema operativo quede en
# una nueva lnea

Notebienquelascomillasconelbackslashquelasprecedenosignificanelfinaldela
cadena,sinoquesignificansoloelcaracterdecomillasdobles.
Lascomillasdoblesdespusdelsaltodelnea,sisignificanelfinaldelacadena.
Enotroaspecto,enalgunascircunstancias,esnecesariopegarunacadenaaunos
caractereslocalesparajuntarambosyqueelresultadosealegiblecomolaunindeestos.
Enestoscasosesnecesariolaintervencindeunareferenciaalnombredelacadena.
Peromejorveamosunejemplo:
$w = "w";
$var = "El sitio es $www.google.com \n";
print $var;
# ESTO IMPRIME: El sitio es .google.com

EstoimprimeElsitioes.google.comyaquePerlreconoceunavariabledenombre$www,
lacualannoestdeclaradayporlotanto,noexisteynoseimprime.
(Recordarsiempreloscaracteresadmitidosenlosnombresdecadena.)
Parapoderhacerestaconcatenacinesnecesariousarunareferenciaalnombredela
variableconlossmbolosdellaves:
$w = "w";
$var = "El sitio es ${w}ww.google.com \n";
print $var;
# ESTO IMPRIME: El sitio es www.google.com

Pag.28

Conejemplossencillosparaautomatizacindetareasenservidores

Estohacequelacadenadeclarada$wcuyocontenidoeswseconcatenealoscaracteres
wwyformeunamezclaresultantedewww,imprimiendosecorrectamente.
3.1.2.2Concatenacindevariables
Estoqueacabamosdeveresunpocoparecidoajuntardosvariablesparaquealimprimir
ambas,elresultadosealaUNINdelasdosvariables.
Estosellamaconcatenacindevariablesyelmododehacerloeselsiguiente:
$hola = "Hola";
$wld = "mundo";
$holamundo = $hola . " " . $wld . "\n";
print $holamundo;
# imprime: Hola mundo

Loexplicamos:
Laconcatenacinsellevaacabomediantelospuntos,esdecir,elpuntoconcatenaunao
masvariablesy/ocadenas,unindolascomosifueranunasola.
Lavariable$holamundoestformadaporlauninde4cadenas,lacadenadelavariable
$hola;despusseuneotraqueesunacadenadesolounespacio,luegolacadenamundo
delavariable$wldyfinalmentelacadenaconelcaracterdelsaltodelnea...

Enotroaspecto,hayotrotipodesintaxisquepermitedelimitarunacadenadecaracteres
paraasignarlasavariables,sonlasetiquetas.
Seutilizancuandolacadenadecaracterescontienevariaslneasy/ocomillasoapstrofes.
Susintaxiseslasiguiente:
$str = <<ETIQUETA;
....
....
ETIQUETA

dondelaETIQUETAesunacadenadecaracterescualquiera.
Elfindelacadenasedeterminaporlanuevalneaquecontienenicamenteelidentificador
delaetiqueta.
stenodebeirprecedidoporunespacionimarcadetabulacin.Porejemplo:
Pag.29

HugoMazaM.Perlbsicodesdecero
$msg = <<ETQT;
hola,
buenos "das",
mundo,
ETQT
print $msg;

Almomentodecorrerelscriptseimprimelosiguiente:
user@host ~$ ./script.pl
hola,
buenos "das",
mundo,
user@host ~$

Notamosqueseimprimeexactamentecomodeclaramoslacadena.
Estoincluyelossaltosdelneafsicos,hastaelltimodeellos,quenossirvepara
posicionarelcursordelpromptdelshelldeUnixenunalneanueva.
Otracosaquehayquenotaresquelaetiquetadefindecadenanollevaelpuntoycoma(;)
caractersticodelosfinalesdeinstruccin,porqueelfinaldelainstruccinyafudeclarado
coneliniciodelaetiqueta.
3.1.3Boleanos
EltipodecadenabooleanaexistealigualqueenC,demodoimplcito,esdecir,unnmero
esfalsosiesigualaceroyverdaderoenelcasocontrario.
Comoelceroestasociadoalacadenavaca(""),cuandounacadenanocontieneningn
caracter,equivaleatenerunvalorfalso,odecero.
Estonosresultatilcuandomanejamosbifurcaciones,buclesyotrasfuncionesdePerl.
Peronoseasuste,loveremosunpocomasadelanteadetalle.
LasvariablesenPerlseasignandemaneradinmicayselesasignaunvalor
predeterminadoenfuncindelcontextodondesetrabaja.
Enuncontextonumricoelvalorpredeterminadodeunavariablees0.
Enuncontextodecadenadecaracteres,elvalorpredeterminadoeslacadena
vaca("").
Estodebetomarseenformamuyseriayaquenosservirparatodotipodefunciones
Pag.30

Conejemplossencillosparaautomatizacindetareasenservidores

dentrodeundesarrollodescriptdePerl,asquegrabmonosbienenlacabezaestaidea
queacabamosdemencionar.
Poresto,esfcildarnosunaideadelosvaloresquetomanpordefectolasvariables
cuandolasdeclaramos.
EnPerl,esmuycomndeclararunavariableantesdeusarseporejemplo,enunbucle,ylo
vemosconelsiguienteejemplo:
# declaramos la variable y no le asigamos ningn valor predefinido.
$variable;
# o bien:
$var = "";

Enamboscasoslavariableposeeunvalordevaco,sinembargo,paraefectosdevalidar
conunavariablesielprocesoesverdaderoofalso(comoveremosmasadelante),ambas
variablestomanelvalordecero(0).Yceroesfalso(verdaderoencualquierotrocaso).

3.1.4Contextodeusodelasvariables
EltipoyelvalordelasvariablesenPerlsedeterminaapartirdelcontexto.
As,unacadenadecaracteresconteniendounvalornumricoserconvertidaenvariable
numricaenuncontextonumrico,comoyalohabamosmencionado.
Estoquieredecirquesideclaramosunavariablequerepresenteunacadenadecaracteres
queseansolonmeros,siposteriormentelausamosdentrodelcontextonumrico,esta
cadenaseconvierteanmeros.
Estonosindicaquepodemoshaceroperacionesalgebricasconestasvariablescomosi
setratarendevariablesnumricasynodecadenasdecaracteres.
Ejemplo:
$pi = 3.1416;
$var = "20";
$suma = $pi + $var;
print $suma , "\n";

#
#
#
#

un nmero real
una cadena de caracteres
sumamos ambas variables
imprime 23.1416

Enalgncasopodremostenerunavariablemezcladaentrenmerosycaracteres.
Pag.31

HugoMazaM.Perlbsicodesdecero

Enestecaso,ysolosilavariablecomienzaconnmeros,Perlsolotomarlosnmeros
inicialesparacalcularlasoperacionesaritmticasyelresto,desdeelprimercaracter
alfabticoqueencuentre,sernignorados:
$var_1 = "20cfv1";
$var_2 = 4;
$res = $var_1 / $var_2;
print $res , "\n";

# para Perl, vale 20 en un contexto numrico


# Perl dice: 20 / 4
# imprime 5

3.2Losarraysolistasindexadas
Debemosantesquenada,comprenderquesunalistadedatos.
Seexpresaunalistadedatosgeneralmentemedianteelusodeparntesis,yaldeclararlos,
losseparamosporcomas(,):
(ElementoUno, ElementoDos, ElementoTres)

Algunasvecespodremosprescindirdelosparntesis.
Sinosdamoscuenta,hemosusadolafuncinprintporejemplo,paramostrarenpantalla
unalistadeelementos:
print $var , "\n";

Lamayoradelasfunciones(comoprint)recorreniterativamenteunalistadeelementos
paraaplicarsufuncinacadaunodeellos.
Laordenanteriorpodemosexpresarlatambindeestaforma:
print ($res , "\n");

Dndonoscuentadequelafuncinprintseaplicaenrealidadaunalistadeelementos,y
larecorreiterativamentepararealizarsuprocesosobrecadaunodeellos.
Ahora,cadaelementodelalistaesunavariableescalaralaqueseleasociaunvalor...
Unarrayesunalistadedatosdetipoescalar,indexadosnumricamente.
Esunalistaordenadasegnlosndicesdesuselementos.
Paradarlenombreaestasvariablesdetipoarray,tambindebenusarcaracteres
Pag.32

Conejemplossencillosparaautomatizacindetareasenservidores

alfanumricosy/ounderscore,ydebensiemprecomenzarconletras.
Estasvariables,detipoarray,seidentificanporelprefijoarroba@.Porejemplo:
@numeros = (2, 1, 667, 23, 2.2, 5, 6);
@letras = ("perro", "gato", "len");
@mezcla = ("hola mundo", 23, "adios", 31.234);

Cuandosetrataderangosdeletrasonmeros,esposibledefinirfcilmenteeserangode
caracteresescalaresmedianteelusodedospuntosseguidos,queunenlosextremosdel
rango.Ejemplo:
# rango de letras minsculas desde la "a" a la "z:
@alfabeto = ( a .. z );
# todos los nmeros comprendidos entre "1" y "100" incluyendo estos:
@numeros = ( 1 .. 100 );
# mas rangos especiales
@array = ( 1.2 .. 5.2 );

# (1.2, 2.2, 3.2, 4.2, 5.2)

# cadenas con el operador espacial "qw"


@array = qw(Juan Pablo Pedro Mara Ana 45); # no necesitamos las comillas
# ni las comas para separar los elementos

Enelltimocaso,vemosalgodiferentealosanteriores,usamosqwparadenotarquelos
elementosdentrodelosparntesisvanentrecomillas.
Estemtodofuncionacuandoningnelementoposeeuncaracterdeespacio,delo
contrariolosepararemoscomovarioselementosdelarray...
Ahora,siyadeclaramosnuestravariabletipoarray,ylatenemosbiendefinidadentrode
nuestroscript,sepreguntarcmoleeroaccederaloselementosindividualesdentrodel
array.
Bien,enestecasoseusanlosndicesdelarrayparaindicarcualposicindentrodeste
queremosaccesar.
Todosloselementostienenunndice,ylosndicescomienzandesdeelcero(0).
Estosndicessecolocanentrecorchetes([])ylavariableahoralaescribimoscomoun
escalar,porqueloselementosdelarraysonescalares.
Asporejemplo,ennuestroarraymezcladodenmerosyletras:
Pag.33

HugoMazaM.Perlbsicodesdecero
@mezcla = ("hola mundo", 23, "adios", 31.234);
# no podemos usar qw()
print $mezcla[0], "\n";
# imprime: hola mundo

Estoimprimirdesdeluego,elprimerelementodelarray(elelementocero)
Enotrosejemplosconelmismoarray:
print $mezcla[1], "\n";

# imprime: 23

print "$mezcla[0] - $mezcla[2]\n";

# imprime: hola mundo - adios

...yestonosmostrmasdetallesdelusodelosndicesdelosarrays.
Igualmentepodremosaccesarvarioselementosdelarraypormedioderangos:
@numeros = (2, 1, 667, 23, 2.2, 5, 6);
@nums = @numeros[1..3];
# @nums = (1, 667, 23)

Nuestronuevoarray@numsconstadeloselementosdel1al3delarray@numeros,osea,
desdeelsegundoelementohastaelcuarto(recordemosquecomienzandesdeelcero)...
Ahora,esposibleasignardirectamentelosvaloresdeloselementosdentrodelarray,
directamenteavariables,estoselogramedianteelusodelosparntesis,queyavimosque
seusanparadeclararlavariabledetipoarrayounalistaordenada:
@anims = ("perro", "gato", "len");

# Lo que existe de un lado...

($pet_1, $pet_2, $pet_3) = @anims;

# existe del otro

print $pet_1, "\n";


print $pet_2, "\n";
print $pet_3, "\n";

# esto imprime: perro


# esto imprime: gato
# esto imprime: len

# Y si solo queremos tomar el primer elemento:


@anims = ("perro", "gato", "len");
($pet_1) = @anims;
print $pet_1, "\n";

# esto imprime: perro

# Ahora vamos a "extraer" el primer elemento al array


($pet_1, @anims) = @anims;
# $pet_1 = perro
# @anims = ("gato", "leon")

Enlaltimalneaquitamoselprimerelementodelarray,quedandonosconunavariable
Pag.34

Conejemplossencillosparaautomatizacindetareasenservidores

escalarsolayunarraydedoselementos.
ExisteunafuncindePerlquehaceestoltimo,sinembargolaveremosmasadelante.
# Y para regresarlo como estaba:
@anims = ($pet_1, @anims);
# @anims = ("perro", "gato", "len")

Aspodemosjugarconlaspropiedadesdeloselementosdelarrayparaaprenderunpoco.
Finalmente,sivemoslassiguienteslneasdecdigo:
@a = (1,2,3);
@b = (5,6,7);
@c = (@a,4,@b,8);

Estasexpresionesgenerantresarrays,(1,2,3),(5,6,7)y(1,2,3,4,5,6,7,8).Estotambinse
llamainterpolacin.
Cuandoincluimosunarraydentrodeotro,Perl"mezcla"ordenadamantelosarray,
insertandounoaunotodossuselementosenlaposicinindicadadecadaarray.
Parahacerarraydearraysdeberemosaprenderacreararraysbidimensionales,que
veremosposteriormente.
Paracrearoinicializarunarrayvaco,hacemosesto:
@array = ();

Estonosfuncionatambinparavaciarunaarrayexistente,dejndolosinelementos.
3.3Loshashes,oarraysdeindexacinliteral,olistasasociativas
Unalistaasociativaestindexadaporparesenlugardendices(comoelarray).Seutiliza
elsignode%paradefinirestetipodelistaasociativa.
Unelementoestindexadoporelanterior,formandoambos,parejasdeltipo(llave,valor),
endondellave=valor.
Accesamoselvalorpormediodelallave.
Veamoselsiguienteconjuntodeelementosdeunhash:
Pag.35

HugoMazaM.Perlbsicodesdecero
%cuotas = ("root", 1000, "maye", 5000, "hugo", 4000);

Sinosimaginamosunsimilconlosarrays,podremosdefinirqueloselementosdeunHash,
seranelelemento0conel1,elelemento2conel3yel4conel5.
EnesteHash,rootvale1000,mayevale256yhugovale4000.
Enestecaso,paraaccederalvalordecualquieradeloselementosde%cuotasdebemos
conocersullave.
Alreferirnosaloselementosdeunhashusamoslasllavesparaencontrarelvalor.
Porejemplo:
%cuotas = ("root", 1000, "maye", 5000, "hugo", 4000);
$id = $cuotas{"maye"};

# $id = 5000

print $cuotas{"hugo"}, "\n";

# imprime 4000

Estalistapuedecompletarseaadiendonuevosvaloresyasociandoacadallave,elvalor
correspondiente.Porejemplo:
$cuotas{"alan"} = 350;

dondelallavees"alan"yelvalorasociadoes350.
Esimportantemencionarqueenestaslistasdeasociacin,lasllavesnopuedenrepetirse,
yesobviopuestoquesitratramosdeagregarunelementoalhash,yelcualnosabemos
queyaexiste,simplementemodificaremoselvalor:
$cuotas{"maye"} = 800;

Aqu,comolallavemayeyaexista,solomodificamoselvalor,ahoralallavemayetiene
unvalorde800enlugarde5000.
Ahora,estemtodosimplededeclararparesdellavevalorpuedeprestarseaerroresde
dedooteclado,sinembargoexisteotraformadedeclararvariablesdeltipohash,yes
medianteelusodecomodinescomoel=>.
Losparesseseparanporcomas.
Pag.36

Conejemplossencillosparaautomatizacindetareasenservidores

Ejemplo:
%cuotas = ("root" => 1000, "maye" => 256, "hugo" => 4000);

Obien,envariaslneasparamejorvisualizacin:
%cuotas = (
"root" => 1000,
"maye" => 256,
"hugo" => 4000
);

Deestaformanonoshacemosbolasconlasmanosalmomentodedeclararunhashcon
unacantidadgrandedeparesllavevalor,porqueorganizamoslalistadepares,unopor
cadalneaarazndellave=>valor.
Hayqueaclararquetantolasllavesdelhashcomosusvalorespuedensercadenasde
textoonmeros.
Asmismosepuedeinclusodeclararelvalordeunallave,comounavariabledeltipoarray.
Estonosllevaacrearvariablesmultidimensionales.
3.4Lasreferencias
Lasreferenciassonuntipodedatosquepermitehacerreferenciaadatoscontenidosen
otraentidad.Noformanunanuevarepresentacindedatos,yaquestossontratados
comountipomsdeescalar($nombre).
Unareferencia,paraexplicarlomejor,esunavariable,cuyocontenidoactualesladireccin
enmemoriadelcontenidoverdaderodelavariable.
Estoes,queapuntahacialadireccinrealendondeseguardalavariableenmemoria.
SiustedconoceC,lasreferenciassonelequivalentealospunterosenC.
AdiferenciadeC,Perlnodeja"huella"delasreferenciasenmemoriasinoquetieneun
mecanismode"papeleradereciclaje"queconsisteenunregistroqueposeelasdiversas
referenciasacadaelementoenmemoriaylasdestruyecuandodescubrequenadiehace
referenciaal.
Paradefinirunareferenciaseusaeloperadordereferenciabackslash,odiagonalinvertida
("\").
Pag.37

HugoMazaM.Perlbsicodesdecero

Noexisteunoperadordederreferencia,aunqueslosmtodos.
Ejemplosprcticosdecreacindereferencias:
$refa
$refb
$refc
$refx

=
=
=
=

\$a;
\@b;
\%c;
\$refb;

#
#
#
#

referencia
referencia
referencia
referencia

a
a
a
a

escalar
array
hash
referencia

(Tambienexistenreferenciasafuncionesyreferenciasaobjetos,peronosonobjetivode
vistadeestemanual)
3.4.1Arrayreferenciadoannimo
Veamosotraformadecrearunareferenciadearray.Observeloscorchetes([]):
$arrayref = [ 'e1', 'e2', 'e3' ];

Aquelarraynotienenombre.Nocreamosprimeroelarrayydespusloreferenciamoscon
elbackslash.
$arrayrefesenrealidad,unareferenciaaunarregloannimo.
$arrayrefapuntaaunadireccinenmemoria.
Cuandonecesitamoscrearunarrayreferenciadoannimo,esnecesariousarlos
corchetes([])paradeclararlascadenasquecontiene.
$arrayRef = [ a, b, c, d, ...n ];

Yparaaccesarloselementos:
$array = [1, 2, 3, 4];
print $$array[2], "\n";

# imprime 3

Comoseve,eldoblesigno$$seusaparaaccesarunelementodelareferencia.
EnPerl5sehaincluidounmtododeabreviarloselementosdelasreferencias:
$array = [1,2,3,4];
print $array->[2], "\n";

# imprime 3 (mas elegante)

Notelossmbolos>queseusanparaaplicarunaseleccindelareferencia.
Pag.38

Conejemplossencillosparaautomatizacindetareasenservidores

$$array[n]y$array>[n]sonlomismo,ambosllamanaunelementodelarrayreferenciado.
3.4.2Hashreferenciadoannimo
Ahora,otraformadecrearunareferenciaahash.Observelasllaves{}.
$hashref = { 'k1' => 'v1', 'k2' => 'v2' };

Cuandonecesitamoscrearunhashreferenciadoannimo,esnecesariousarlas
llaves{}paradeclararlosparesquecontiene.
$hashref = {
'k1' => 'v1',
'k2' => 'v2',
'k3' => 'v3'
};

Aquelhashnotienenombre.Nocreamosprimeroelhashydespusloreferenciamoscon
elbackslash.
$hashrefesunareferenciaaunhashannimo.
$hashrefapuntaaunadireccinenmemoria.
Yparaaccesarloselementosdelhashreferenciado:
$array = {1 => 2, 3 => 4, 5 => 6};
print $$array{3}, "\n";
# imprime 4

Comoseve,eldoblesigno$$seusaparaaccesarunelementodelareferencia.
Igualmente,unmtododeabreviarloselementosdelasreferencias:
# el mismo array:
$array = {
1 => 2,
3 => 4,
5 => 6
};
print $array->{3}, "\n";

# imprime 4

Notelossmbolos>queseusanparaaplicarunaseleccindelareferencia.
$$array{n}y$array>{n}sonlomismo,ambosllamanaunelementodelhashreferenciado.
Sepuedenrealizarreferenciasareferenciasyarreglosareferenciasdeformaquelos
arraysmultidimensionalessecreenconmuchafacilidad.
Pag.39

HugoMazaM.Perlbsicodesdecero

Cuandounareferenciaesdereferenciadaseobtieneeldatoreal.
# generamos las referencias
$refa = \$a;
# referencia
$refb = \@b;
# referencia
$refc = \%c;
# referencia
$refx = \$refb;
# referencia

a
a
a
a

escalar
arreglo
hash
referencia

# extraemos las variables de las referencias


${$refa}
# de-referencia de $refa, esto es, el valor de $a
@{$refb}
# de-referencia de $refb, esto es, el valor de @b
%{$refc}
# de-referencia de $refc, esto es, el valor de %c

Sitratamosdeimprimirunareferenciatratndolacomounavariable,lonicoquenoshade
mostraresalgocomoesto:
print $ref, "\n";
SCALAR(0x8060284)

oquizs
HASH(0x8060308)

ARRAY(0x9d5e880)

Quesonlasdireccionesenmemoriaendonderealmentesealmacenaelcontenidodela
variable.
Yclaroquenosdaunaideadeltipodevariablequecontiene.
3.5Arraysbidimensionales
Existirnmuchasocasionesenquesernecesariocrearmatricesdedatosendondestos
estnordenados(yseanaccesados),enformabidimensional.
Ypodemosdemaneramuyfcil,creararraysdeestetipodelasiguientemanera:

Pag.40

Conejemplossencillosparaautomatizacindetareasenservidores
@arraybidimensional = (
['Casa', 'Carro', 'Moto'],
['Perro', 'Gato', 'Caballo'],
['Calle', 'Ciudad', 'Pais'],
[22, 303, 405]
);

Observeque,cadalnea(lista)dedatosestdeclaradamedianteelusodecorchetes[].
Yloselementosdentrodeloscorchetesesunaarraydeelementosescalares.
Estonosdaunaidea,quepodemosdeclararunarraybidimensionalapartirdevarios
arrays:
@bienes = ('Casa', 'Carro', 'Moto');
@animales = ('Perro', 'Gato', 'Caballo');
@direccion = ('Calle', 'Ciudad', 'Pais');
@numeros = (22, 303, 405);
@arraybidimensional = (
[@bienes],
[@animales],
[@direccion],
[@numeros],
);

Ytenemosexactamenteelmismoarraydelprincipio.
Ahora,quhacemosparaaccesaracadaelementodelarraybidimensional?
Bueno,yasabemosquepodemosaccesaraunelementosimpledeunarraymono
dimensionalconloscorchetes,ahorasoloagregamosunsegundocorchetepara
acercarnosaldatoescalarrealdelamatriz:
@array = (
['Casa', 'Carro', 'Moto'],
['Perro', 'Gato', 'Caballo'],
['Calle', 'Ciudad', 'Pais'],
[22, 303, 405]
);
print $array[1][1] , "\n";

# imprime: Gato
# o sea, el segundo elemento
# de la segunda lista

print $array[0][0] , "\n";

# imprime: Casa

Elprimercorcheterefierealaslistas,elsegundocorcheterefierealelementodeesalista
enparticular.
Pag.41

HugoMazaM.Perlbsicodesdecero

3.6Arraysbidimensionalesreferenciadosannimos
Recordemosunpoco,comocrearunarrayreferenciadoannimo:
$arrayref = ['xxx', 'yyy', 'zzz'];

Yaccesamosalosdatosdeestaforma:
print $$arrayref[0];

obien,delamaneramascomnyelegante:
print $arrayref->[1];

Ahora,enigualformacomocreamosunarraybidimensional,podemoscrearunarray
bidimensionalreferenciadoannimo:
$arrayref = [
['Casa', 'Carro', 'Moto'],
['Perro', 'Gato', 'Caballo'],
['Calle', 'Ciudad', 'Pais'],
[22, 303, 405]
];

Nuevamenterecalcamosqueunavariablereferenciadaessoloundatoescalar,porloque
esunavariablequesedeclaraconelsignodepesos$,asmismo,notequeusamoslos
corchetesparadeclararunarrayreferenciado.
Enestecasoesunarrayreferenciadobidimensional.
Yesannimoporquenuncadeclaramosprimeroelarrayydespusloreferenciamosconel
backslash($array=\@array),sinoquelocreamos"alvuelo".
Bueno,yatengomiarraybidimensionalreferenciadoannimo,yahora,comoloacceso?
Simple:
print $$arrayref[0][0];

# imprime Casa

bien,delamaneramascomnyelegante:
print $arrayref->[2][0];

# imprime Calle

Elprimercorcheterefierealaslistas,elsegundocorcheterefierealelementodeesalista
enparticular.
Pag.42

Conejemplossencillosparaautomatizacindetareasenservidores

3.7Hashesmultidimensionales
Apartedelosarraysbidimensionales,loshashesmultidimensionalesseutilizanpara
asociarmasdeunvaloralaclave,veamoselsiguienteejemplo:
%hash = (
'Manzana'
'Tocino Canadiense'
'Alcachofa'
'Remolacha'
'Sazonador Especies'
'Tortilla'
'Salsa picante'
);

=>
=>
=>
=>
=>
=>
=>

[4,
[1,
[3,
[4,
[1,
[1,
[1,

"Delicious red", "mediano"],


"paquete", "1/2 pound"],
"lata", "8.oz."],
"lata", "8.oz."],
"bote", "3 oz."],
"paquete", "16 oz."],
"bote", "8 oz."]

Paraextraerunvalorparticular,alconjuntodevaloresdebetratrselecomounarray,ya
quesinosdamoscuenta,separadosporcomasonunalistadeelementos.
print $hash{"Tocino Canadiense"}[1];

# imprime paquete

Lainstruccinanteriormostrarenpantallaelvalorpaquetequeeselsegundoelemento.
Esposibleasignarunarrayaunvalordeclave.
@ajos = (4, "Ajo", "mediano");
$hash{"Ajo"} = [@ajos];
# tiene que ser dentro de corchetes
print $hash{"Ajo"}[1];
# imprime Ajo

Esposibleasociararreglosdelongitudvariableaunamismaestructurahash.Elsiguiente
programapermiteimprimirunhashconarreglosdedistintalongitudasociadosalasclaves.
foreach my $key (sort keys %hash) {
print "$key: \n";
foreach my $val ( @{$hash{$key}} ) {
print "\t$val\n";
}
print "\n";
}

Posteriormenteentenderemosesteltimobucle.

Pag.43

HugoMazaM.Perlbsicodesdecero

3.8Hashesmultidimensionalesreferenciadosannimos
Tambinpodremoscrearhashesmultidimensionalesreferenciadosannimostanfcilmente
comolosarraysbidimensionalesannimos:
$hash = {
'Manzana'
'Tocino Canadiense'
'Alcachofa'
'Remolacha'
'Sazonador Especies'
'Tortilla'
'Salsa picante'
};

=>
=>
=>
=>
=>
=>
=>

[4,
[1,
[3,
[4,
[1,
[1,
[1,

"Delicious red", "mediano"],


"paquete", "1/2 pound"],
"lata", "8.oz."],
"lata", "8.oz."],
"bote", "3 oz."],
"paquete", "16 oz."],
"bote", "8 oz."]

Recordemosqueparacrearunhashreferenciadousamoslasllaves"{}"paracrearlos.
Yparaaccesarlosvaloresdelasllavesdelhash:
print $$hash{"Tocino Canadiense"}[1] , "\n";

Obien,delaformamascomnyelegante:
print $hash->{"Tocino Canadiense"}[1] , "\n";

# imprime paquete

Estonosdebeimprimir"paquete",queeselsegundoelementodelarrayquecorresponde
alvalordelallave"TocinoCanadiense".

Pag.44

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO4

OperadoresenPerl
Pag.45

HugoMazaM.Perlbsicodesdecero

Pag.46

Conejemplossencillosparaautomatizacindetareasenservidores

4.OperadoresenPerl
EnPerl,sedistinguentrestiposdeoperadoresdedatos.Ydependendelarepresentacin
dedatossobrelaqueestamosactuando:
1. Operadoresparaescalares.
2. Operadoresparaarrays.
3. Operadoresparahasheslistasasociativas.
4.1Operadoresparaescalares
Estetipodeoperadoressepuedensubdividiren:

Operadoresaritmticos.
Operadoresrelacionales.
Operadoreslgicosobooleanos.
Operadordeseleccin.
Operadoresdeasignacin.
Operadoresdebits.

4.1.1Operadoresaritmticos
Adelantamosenunejemploanterior,quepodemossumardosvariablesconelsignode+
entreambasvariables,eneltemaLosEscalaresen3.1.4.
Ahoramencionaremosalgunosotrostiposbsicosdeoperacionesentrevariables
escalares.
Resta:
(Nota:sivaarealizarpruebas,noolvidelaprimeralneadelarchivo)
#!/usr/bin/perl
$var1 = 50;
$var2 = 40;
$resta = $var1 - $var2;
print $resta , "\n";

# esto imprime 10

Pag.47

HugoMazaM.Perlbsicodesdecero

Seusaelguinmedio(osignoderesta)paradenotarunaresta.
Divisin:
#!/usr/bin/perl
$var1 = 50;
$var2 = "2";
$division = $var1 / $var2;
print $division , "\n";

# esto imprime 25

Seusaelsignodeslash,obarrainclinadaparadenotarunadivisin.
Multiplicacin:
#!/usr/bin/perl
$var1 = 50;
$var2 = 2;
$multi = $var1 * $var2;
print $multi , "\n";

# esto imprime 100

Seusaelasteriscoparadenotarunamultiplicacin.
Ahora,podemoshacervariasoperacionesaritmticasdentrodeunasolainstruccin.
Existeunajerarquadeejecucindeoperacionesaritmticascuandohacemosvariasde
estasdentrodeunainstruccin.
Sinembargo,enformaprcticaesmejorutilizarsiemprelosparntesisparaasegurarnos
quelainstruccinseejecuteenelordenquedeseamos.
Ejemplo(consustitucindevariable):
#!/usr/bin/perl
$var1 = 50;
$var2 = 2;
$var3 = 20;
$var4 = 4;
$resultado = (($var1 * $var2) / $var3) - $var4;
# ((50 * 2) / 20) - 4
print "El resultado es $resultado \n";
# esto imprime: El resultado es 1

Elmismobusdevariables,condiferenteorganizacindeparntesis:
#!/usr/bin/perl
$var1
$var2
$var3
$var4

Pag.48

=
=
=
=

50;
2;
"20";
4;

Conejemplossencillosparaautomatizacindetareasenservidores
$resultado = ($var1 * $var2) / ($var3 - $var4);
print $resultado , "\n";

# (50 * 2) / (20 - 4)

# esto imprime: 6.25

Ahora,losoperadoresaritmticossepuedenusarenPerlparaincrementar
automticamenteelvalordeunavariableobien,decrementarlos.
++y

(doblessignos+y,sinespacios)

Ademsdelaaccindemodificarlavariabledevuelvenelvalordeestavariable.
Losoperadoresdeincrementoodecrementopuedenirdelanteodetrsdelavariable,
teniendodiferentesignificadoencadacaso.
Sieloperador++sesitadespusdelavariablesedenominadepostincremento,
haciendoqueprimerodevuelvaelvalorydespusseincrementelavariable.
Ejemplo:
$k = 2;
$n = $k++;
print $n, "\n";
print $k, "\n";

# el valor de k se asigna a n y despus se incrementa k


# imprime 2
# imprime 3

Porotrolado,sieloperador++sesitaantesdelavariablesedenominapreincrementoy
hacequeprimeroseincrementelavariableydespusdevuelvaelvalor.
Ejemplo:
$k = 2;
$n = ++$k;
print $n, "\n";
print $k, "\n";

# primero se incrementa k y luego se asigna a n


# imprime 3
# imprime 3

Lomismosucedeconeloperadordedoblesignoderesta().
4.1.2Operadoresrelacionales
EnPerl,existendostiposdeoperadoresrelacionales:
Operadoresdevaloresnumricos
Operadoresdecadenasdecaracteres.
Pag.49

HugoMazaM.Perlbsicodesdecero

Lalistadeoperadoresesequivalente.
Peroveamoslasiguientetabla:
Operadorrelacional

Numrico

Caracteres

Iguala

==

eq

Noigual

!=

ne

Menorque

<

lt

Mayorque

>

gt

Menoroigual

<=

le

Mayoroigual

>=

ge

Perlevalalasoperacionesresultantesydevuelvefalsooverdaderoensucaso:
$dos = 2;
$tres = "tres";
($dos eq "dos")
($dos == 3)
($dos == 2)
($tres eq "tres")

#
#
#
#

devuelve
devuelve
devuelve
devuelve

un
un
un
un

valor
valor
valor
valor

falso o cero
falso o cero
verdadero o 1
verdadero o 1

Sobreelusodeestosvaloresdevueltosnonospreocupemosahoraparaquenossirven,
prontoloveremos.
Apartedelosoperadoresquehayenlatablacabedistinguirotrosoperadores
caractersticosnicamentedellenguajePerl.
cmp
Esteoperadoresutilizadoparacompararcaracteres,demaneraque,retorna0silos
caracterescomparadossoniguales,1silacadenadeladerechaseencuentraalcomienzo
deladelaizquierda,y1enelcasocontrario.Paraaclararelfuncionamientodeeste
operadorheaquunejemplo:
'uno' cmp
'uno dos'
'dos uno'
'dos' cmp

Pag.50

'uno'
cmp 'uno'
cmp 'uno'
'uno'

#
#
#
#

devuelve 0
devuelve 1
devuelve -1
devuelve -1

Conejemplossencillosparaautomatizacindetareasenservidores

<=>
Esteoperadorseutilizaparacompararvaloresnumricos,retornando0cuandoson
iguales,1cuandoelterminodeladerechaesmenorqueeldelaizquierday1enelcaso
contrario.
1 <=> 1
12 <=> 1
1 <=> 21

# devuelve 0
# devuelve 1
# devuelve -1

4.1.3Operadoreslgicosobooleanos
Losoperadoreslgicosestnligadosalosrelacionalesyaquenormalmenteestos
operadoresseusanentreresultadosdeoperacionesrelacionales.
and

&&

or

||

not

Estosoperadorescomplementanlosrelacionales,evaluandodosomasexpresiones.
Eloperadorlgico&&evaladosexpresionesomasydevuelveverdaderosoloencasode
quetodaslasexpresionesevaluadasresultenverdaderas.
Porsuparte,eloperador||evaladosomasexpresionesydevuelveverdaderocuando
solounadeellasresulteverdadera,noimportasilasdemsresultanfalsas.
Yunavezquesedisponedeunoovariosdatosdetipobooleano,estossepueden
combinarenexpresioneslgicasmediantelosoperadoreslgicos(AND,OR,NOT,...).Un
ejemplodecombinacionesdeestetipodeexpresionesseran:
verdaderoANDfalso >falso
falsoORverdadero
>verdadero
verdaderoORverdadero
>verdadero
falsoANDfalso
>falso
Ejemplosprcticos:

Pag.51

HugoMazaM.Perlbsicodesdecero
$dos = 2;
$tres = 3;
($dos == 2 && $tres == 3)

# devuelve verdadero 1 porque ambas son


# verdaderas

($dos == 2 && $tres == 2)

# devuelve falso 0
# ya que una condicin es falsa

($dos == 2 || $tres == 2)

# devuelve verdadero 1 ya que


# una de las dos expresiones es verdadera

($tres != 3)

# devuelve falso 0, ya que $tres s es igual a 3

4.1.4Operadoresdeseleccin
Esunoperadortriarioquerequiereunacondicinydosexpresionesqueseejecutan
cuandolosvaloresresultanverdaderoofalso.
Perlejecutaunaexpresinuotradependiendodelresultadofalsooverdaderodela
condicin.
Suformatoeselsiguiente:
Condicin?Exp1:Exp2
PerlevalalaCondicinydevuelveExp1siesverdadero,siesfalso,
devuelveelvalordeExp2.
Porejemplo:
$x = 7;
$i = ( $x < 8 ? 6 : $x + 1 ); # si $x<8 entonces i=6, si no $i=$x+1
print $i, "\n";
# imprime 6, porque $x es menor que 8

otroejemplo:
$x = 7;
$i = ( $x < 5 ? 6 : $x + 1 ); # si $x<8 entonces i=6, si no $i=$x+1
print $i, "\n";
# imprime 8 ( o sea $x + 1 )
# porque $x no es menor que 5

Pag.52

Conejemplossencillosparaautomatizacindetareasenservidores

4.1.5Operadoresdeasignacin
Unaasignacintambinesunoperadorquedevuelvelavariablemodificada.
4.1.5.1Operadordeasignacin=
Sinonoshabamosdadocuenta,yahemosestadousandounoperadordeasignacinen
loquellevamosledo,eseloperadordeasignacin=:
$x = 7;

Perlasignaalavaiable$xelvalorcompletodeloqueestdelladoderechodela
expresin,medianteeloperadordeasignacin=.

4.1.5.2Operadordeasignacin+=
Incrementaelvalornumricodelavariabledelladoizquierdoconelvalordelacadenadel
ladoderecho:
$x = 7;
$x += 2;

# ahora $x vale 9

4.1.5.3Operadordeasignacin=
Decrementaelvalornumricodelavariabledelladoizquierdoconelvalordelacadenadel
ladoderecho:
$x = 7;
$x -= 2;

# ahora $x vale 5

4.1.5.4Operadordeasignacin*=
Multiplicaelvalornumricodelavariabledelladoizquierdoconelvalordelacadenadel
ladoderecho:
$x = 7;
$x *= 2;

# ahora $x vale 14

Pag.53

HugoMazaM.Perlbsicodesdecero

4.1.5.5Operadordeasignacin/=
Divideelvalornumricodelavariabledelladoizquierdoconelvalordelacadenadellado
derecho:
$x = 8;
$x /= 2;

# ahora $x vale 4

4.1.5.5Operadordeasignacin.=
Concatenalavariabledelladoizquierdoconelvalordelacadenadelladoderecho:
$x = "Hola";
$x .= " mundo";
print "$x \n";

# es igual a escribir $x . " mundo"


# imprime: Hola mundo

EnlasiguientetablaveremoslosoperadoresdeasignacincontenidosenPerl,losque
hemosvisto,masotrosmenosusados,delosqueellectorpuededescubrirsuuso
intuitivamente.

Pag.54

Operador

Uso

Equivalencia

$a=$b+1;

+=

$a+=3;

$a=$a+3;

$a=3;

$a=$a3;

*=

$a*=2;

$a=$a*3;

**=

$a**=2;

$a=$a**3;

/=

$a/=3+$b;

$a=$a/(3+$b);

%=

$a%=8;

$a=$a%8;

.=

$a.=hola;

$a=$a.hola;$a=${a}hola;

>>=

$a>>=1;

$a=$a>>1;

<<=

$a<<=$b;

$a=$a<<$b;

&=

$a&=(c+=3);

$c=$c+3;$a=$a&$c;

^=

$a^=2;

$a=$a^2;

|=

$a|=$c;

$a=$a|$c;

Conejemplossencillosparaautomatizacindetareasenservidores

4.1.6Funcionesdefinidasparamanejodecadenasdecaracteres
Perlposeeunaseriedefuncionesdefinidasparaelmanejodelascadenasdecaracteres,
lascualesnosayudanmuchsimoenlastareasdeadministracindedatos.
Acontinuacinnombraremoslasfuncionesbsicasparaefectuardichotratamiento:
length
length($cadena).

Estafuncinnospermiteconocerlalongituddeunacadenadecaracteres.
Porejemplo:
$cadena = "hola";
$largo = length($cadena);

chop

# $largo = 4

chop($cadena).

Eliminaelltimocaracterdelacadenayretornadichocaracter.
Estafuncinseusamuchoparaeliminarelcaracterdesaltodelneaquecontienenlas
cadenasqueseintroducenporteclado,obien,delaslneasqueseleendeunarchivo,las
cualescontienentambinunsaltodelneaalfinal.
Ejemplo:
print "Teclea algo y pulsa enter:\n";
# En Perl, para capturar datos desde el teclado
# usamos la entrada estandard <STDIN>
$input = <STDIN>;
# $input contiene el "enter" , \n (salto de lnea)
chop($input);

# ahora $input ya no contiene el ltimo caracter: "\n"

Cabemencionarquesituviramoslaorden:
$ultimo = chop($input);

# $ultimo contendr el salto de lnea


# porque chop regresa el caracter extrado

Pag.55

HugoMazaM.Perlbsicodesdecero

chomp
Aligualquechop,eliminaelltimocaracterdelacadenayretornadichocaracter.
Adiferenciadechop()queeliminacualquiercaracterseacualsea,chomp()sloeliminael
ltimocaractersistesetratadeuncaracterdesaltodelnea.Porloquesiempreque
necesitemoseliminarnicamenteuncaracterdenuevalneaesmsseguroutilizar
chomp().
Losejemplosanterioresfuncionanadecuadamente,soloagregaremosejemplosdela
propiedadrecursivadechomp():
@array = ('Hola\n', 'mundo\n', 'Somos', 'todos\n');
chomp(@array);

Enesteejemplo,hacemosunrecorterecursivodecadaunodeloselementosdelarreglo,
demodoquecadaunodelasvariablesquedasinelltimocaracterdesaltodelnea.
Enelcasodeltercerelemento,Somos,nolequitaelltimocaracter(queseralaletras),
porqueeseltimocaracternoesunsaltodelnea.
index

index(cadena, sub-cadena, [posicin]).

Estafuncinretornalaposicindelaprimeraocurrenciadelasubcadenadentrodela
cadenaindicada.
Elparmetroposicinindicaelnmerodecaracteresapartirdelcualdebecomenzarla
bsqueda.
Siseomiteesteparmetroseconsideraquenosedeseaignorarningncarcter,esdecir,
seconsideraposiciniguala0.
Sinoseencuentralasubcadenalafuncindevuelvelaposicindesdelaquecomienzaa
buscar1,estoes,elparmetroposicinmenos1.
Ejemplo:
$cadena = "El automvil";
$subcadena = "auto";
$pos = index($cadena, $subcadena);
$pos = index($cadena, $subcadena, 6);

Pag.56

# la sub-cadena a buscar
# $pos = 4
# $pos = 5 (6-1)

Conejemplossencillosparaautomatizacindetareasenservidores

rindex
rindex(cadena, sub-cadena, [posicin]).

Estafuncintrabajaigualqueindex()salvoqueretornalaltimaocurrenciadelasub
cadenadentrodelacadena.
Elparmetroposicinindicaelnmerodecaracteresapartirdelcualdebecomenzarla
bsqueda.
Sinoseencuentralasubcadenalafuncindevuelve[posicin]menos1.
Ejemplo:
$cadena = "Los celos del celoso";
$sub = "celos";
$pos = rindex($cadena, $sub);

# celos aparece dos veces


# $pos = 14;

substr
substr(cadena, inicio, [longitud]).

Estafuncinextraeunasubcadenadelacadenadada,desdelaposicinindicadapor
inicio,hastaelnmerodecaracteresindicadoporlongitud.
Sielparmetrolongitudseomitesetomarlasubcadenaquevadesdeelparmetroinicio
hastaelfinaldelacadena.
Elprimercarcterdeunacadenaeselqueestaenlaposicincero.
Ejemplo:
$cadena = "Universidad Autnoma de Nuevo Len";
$sub = substr($cadena, 25, 5);
# $sub = "Nuevo"
# ahora no ponemos el parmetro longitud:
$sub = substr($cadena, 25);
# $sub = "Nuevo Len"

uc
Deuppercase,devuelvelavariablequeselepasecomoargumento,perocontodoslos
caracteresenmaysculas.
Pag.57

HugoMazaM.Perlbsicodesdecero

Ejemplo:
$a = "Anastacio";
$b = uc($a);
print $b;
# imprime: ANASTACIO

lc
Delowercase,eslafuncincontrariaauc,devuelveunavariablequeselepasacomo
argumento,peroconloscaracteresenminsculas.
Ejemplo:
$a = "ANASTACIO";
$b = lc($a);
print $b;
# imprime: anastacio

Funcionesnumricas

Pag.58

abs($x)

Devuelveelvalorabsoluto

cos($x)

Cosenoenradianes

exp($x)

Exponencial

hex($x)

TransformaunnumeroHexadecimaladecimal

int($x)

Devuelvelaparteenteradelnmero

log($x)

Logaritmonatural(basee)

srand($x)

Inicializaelgeneradordenmerosaleatorios

rand($x)

Devuelveunnmerorealenelintervalo[0,$x)

sin($x)

Senoenradianes

sqrt($x)

Razcuadrada

Conejemplossencillosparaautomatizacindetareasenservidores

Unsoloejemplosimple:
$a = 19.265257193;
$b = int $a;
print $b;

# devuelve la parte entera de $a


# imprime 19

Obien,maseleganteymenoslneas:
$a = 19.265257193;
print int $a;

# imprime 19

4.2FuncionesparaArrays
4.2.1Funcinpush
Agregaunelementoalfinaldelarray:
@array = ('carro', 'moto', 'lancha');
push (@array, 'camin');
$otro = "avin";
push (@array, $otro);
print $array[4], "\n";

# 3 elementos iniciales

# ahora @array tiene 4 elementos


# y el ltimo [3] es 'camin'
# ahora @array tiene 5 elementos
# y el ltimo [4] es 'avin'
# imprime: avin

4.2.2Funcinpop
Alcontrariodepush(),pop()extraeyademsdevuelveelltimoelementodeunarray:
@array = ('carro', 'moto', 'lancha', 'camin', 'avin');

# 5 elementos

pop(@array);

# ahora @array queda con 4 elementos

$ultimo = pop(@array);

# ahora @array queda con 3 elementos


# y asigna el elemento extrado a la
# variable $ultimo

print "$ultimo \n";

# imprime: camin

Pag.59

HugoMazaM.Perlbsicodesdecero

4.2.3Funcinshift
Extraeydevuelveelprimerelementodeunarray:
@array = ('carro', 'moto', 'lancha', 'camin', 'avin');

# 5 elementos

shift(@array);

# ahora @array queda con 4 elementos


# le hemos quitado 'carro'

$primero = shift(@array);

# ahora @array queda con 3 elementos


# y asigna el elemento extrado a la
# variable $primero

print "$primero \n";

# imprime: moto (era el primer elemento)

4.2.4Funcinunshift
Alcontrariodeshift(),unshift()insertaunelementoaliniciodeunarray:
@array = ('lancha', 'camin', 'avin');
unshift(@array, "moto");

# 3 elementos

# ahora @array tiene 4 elementos

$otro = "carro";
unshift(@array, $otro);

# ahora @array tiene 5 elementos

print "$array[0] \n";

# imprime carro, el primer elemento


# el cual fue insertado al ltimo

4.2.5Funcinsplit
Generaunalistaordenadaporndices(oarray),apartirdeunacadena.
Lacadenadebecontenerunpatrncomouncaracterounacadenadecaracteres,lacual
servirdeanclaparasepararcadaelementoqueformarelarray.
Peromejorveamosunejemplo:
$cadena = "Casa==Edificio==Choza==Hotel";
@arraynuevo = split( "==", $cadena);
print $arraynuevo[1], "\n";

Pag.60

# imprime: Edificio
# el segundo elemento del nuevo array

Conejemplossencillosparaautomatizacindetareasenservidores

Notequeelpatrnquetomamoscomobaseparasepararloselementosdelnuevoarray,es
elconjuntodecaracteresdoblesignoigual:==.
Estoscaracteresseeliminanalformarelarray.
Lafuncinsplit(),soportatresargumentos,elprimeroyasabemos,eslacadenaocadenas
quesonnuestropatrnseparador,elsegundoeslacadenaapartirdelacualgeneraremos
elarray,yexisteunterceroquedebeserunnmeroentero,elcualesopcionalyconeste
leindicamosasplit(),ellmitedeelementosquedeseamosquecontengaelarray.
Estoharquedespusdecompletarloselementoscargadosalarray,elrestodelos
separadoresseaignorado,formandotodoelresto,elltimoelementodelarray.
Ejemplo:
#/usr/bin/perl
$cadena = "Casa==Edificio==Choza==Hotel";
@arraynuevo = split("==", $cadena, 3);
print $arraynuevo[2], "\n";

# imprime: Choza==hotel
# el ltimo elemento del nuevo array

NotequeChoza==Hotelnosesepararonporelpatrnelegido(==),puessoloescogimos3
elementosmximos,ignorandoelrestodelascadenasseparadoras.
4.2.6Funcinjoin
Tomaunalistaordenadaporndicesoarray,yconcatenaloselementosdeesalistaoarray,
medianteunaounascadenas.
Esrealmente,locontrariodesplit():
Ejemplo:
#/usr/bin/perl
@array = ("Casa", "Edificio", "Choza", "Hotel");
$cadenanueva = join("--", @array);
print $cadenanueva, "\n";

# imprime: Casa--Edificio--Choza--Hotel

Concatenamostodosloselementosdelarray@arrayinterponiendounseparadorqueen
Pag.61

HugoMazaM.Perlbsicodesdecero

estecaso,usamoslacadenadobleguin.
Elseparadorpuedesercualquiercaracter,inclusoelespacio,ounacadenavaca:"".
4.2.7Funcinsort
Ordenaloselementosdeunarrayenformaascendente.
Ejemplo:
#!/usr/bin/perl
@array = (5, 2, 1, 3, 4);
@array = sort(@array);

# ahora @array = (1, 2, 3, 4, 5)

print $array[4], "\n";

# imprime 5

Lomismopasaconcaracteresalfabticos:
#!/usr/bin/perl
@array = ('a', 'e', 'b', 'd', 'c', 'B');
@array = sort(@array);

# ahora @array = (B, a, b, c, d, e)

print $array[5], "\n";

# imprime e

print $array[0], "\n";

# imprime B

NotequelasLetrasMaysculastienenprecedenciasobrelasminsculas.
Rogamosallectorbuscarladocumentacindesorten:
http://perldoc.perl.org/functions/sort.html
yquetratedecomprenderbienestafuncin,puesesmuytilenelanlisisdedatos.
4.2.8Funcinreverse
Invierteelordencompletodeloselementosdeunarray.
Ejemplo:
#/usr/bin/perl

Pag.62

Conejemplossencillosparaautomatizacindetareasenservidores
@array = (5, 2, 1, 3, 4);
@array = reverse(@array);

# ahora @array = (4, 3, 1, 2, 5)

print $array[0], "\n";

# imprime 4

Ysisenosocurremezclarreverse()conelanterioroperadorestudiado,sort():
#/usr/bin/perl
@array = (5, 2, 1, 3, 4);
@array = reverse( sort(@array) );

# ordenamos y despus invertimos


# ahora @array = (5, 4, 3, 2, 1)

print $array[0], "\n";

# imprime 5

Adicionalmente,podemosreducirexpresiones,comolohacemosenmatemticas,soloque
enPerl,setratadeaplicarnuestralgica:
Elltimoscriptlopodemosreducira:
#/usr/bin/perl
print reverse (sort(5, 2, 1, 3, 4)), "\n";

Aplicamoslafuncinprintalafuncinreverse,yestaseaplicaadoselementos,lafuncin
sortyelsaltodelnea,lafuncinsortaplicasusbondadessobreunalistadeelementos.
Elresultado...seimprime54321,yunsaltodelnea...
4.2.9Funcin$#
Esteoperadornospermiteconocerelltimondicedeunamatrizdeltipoarrayreferenciado
annimobidimensional.
Examinemoselsiguientescriptqueyaloescribiremoscompleto:

Pag.63

HugoMazaM.Perlbsicodesdecero
#!/usr/bin/perl
$array = [
# creamos el array referenciado
['uno', 'dos', 'tres'],
# primera lnea o sub-array
['cuatro', 'cinco', 'seis'],
# segunda lnea o sub-array
['siete', 'ocho', 'nueve']
# tercera lnea o sub-array
];
print $#{$array}, "\n";

# imprime 2, que es el ltimo ndice de lneas


# o sea, que contiene del 0 al 2

print $#{$array} + 1, "\n";

# imprime 3, que es la cantidad real de lneas

exit;

# salimos elegantemente del script

Sinuestravariablereferenciadacontienetreselementossubarrays,estonosvaadevolver
2,queeselltimondicedelsubarraycontenidoenlamatriz.
4.2.10Funcinmap
Otrafuncinimportantequepodemosusaresmap,lacualrecorreiterativamentelos
elementosdeunarrayolista,ypuedecambiarlossilodeseamos.
Lasintaxises:
map { INSTRUCCIONES_POR_CADA_ELEMENTO } @array;

Estafuncintambindevuelveelresultadoaunavariablesimilar:
@otroarray = map { INSTRUCCIONES_POR_CADA_ELEMENTO } @array;

Ejemplo:
@array = (1, 2, 3, 4, 5);
map { $_ += 10 } @array;

# ahora @array = (11, 12, 13, 14, 15)

4.2.11Funcingrep
Devuelveunalistaquecontieneloselementosdeunarraydondelaexpresines
verdadera.
Sintaxis:
Pag.64

Conejemplossencillosparaautomatizacindetareasenservidores

grep(EXPRESIN,@array);
Ejemplo:
@a = ("a1", "a2", "b1", "b2", "c1", "c2");
@b = grep ( /^b/, @a );
# El lector no ha ledo sobre esta
# expresin, mas adelante lo veremos
map { print $_, " " } @b;

# imprime: b1 b2 usando la funcin anterior

Yaqueannohemosestudiadolasexpresionesregulares,enestecasolepediremosal
lectorqueimaginequelepedimosagrepquebusqueloselementosdelarrayque
comienzanconlaletrab.
Posteriormenteustedpodrregresaraentenderbienestafuncin.
4.3FuncionesparaHashes
4.3.1Funcinkeys
DevuelveunalistadelasllavesdeunalistaasociativaoHash.
Ejemplo:
#!/usr/bin/perl
%hash = (
'carro' => 'azul',
'moto' => 'roja',
'camion' => 'verde',
'avion' => 'amarillo'
);
@arraykays = keys(%hash);

# @arraykeys = (carro, moto, camion, avion)

print $arraykeys[1], "\n";

# imprime moto

Recordemosqueunhashestformadoporunalistadeparesllavevalor.
4.3.2Funcinvalues
DevuelveunalistadelosvaloresdeunalistaasociativaoHash.
Pag.65

HugoMazaM.Perlbsicodesdecero

Ejemplo:
#!/usr/bin/perl
%hash = (
'carro' => 'azul',
'moto' => 'roja',
'camion' => 'verde',
'avion' => 'amarillo'
);
@lsvalues = values(%hash);

# @lsvalues = (azul, roja, verde, amarillo)

print $lsvalues[2], "\n";

# imprime verde

4.3.3Funcindelete
SuprimeoeliminaelementosdeunalistaasociativaoHash.
Ejemplo:
#!/usr/bin/perl
%hash = (
'carro' => 'azul',
'moto' => 'roja',
'camion' => 'verde'
);
delete $hash{'moto'};

# eliminamos un elemento del hash

@arraykays = keys(%hash);

# @arraykeys = (carro, camion)

print $arraykeys[1], "\n";

# imprime camion

4.3.4Funcineach
Esteoperadorrecorreiterativamentetodoslosparesllavevalordeunalistaasociativao
Hash,permitiendoaccederrecursivamenteacadaparmedianteelusodeestructurasde
control.
Lasintaxisoperativaes:

Pag.66

Conejemplossencillosparaautomatizacindetareasenservidores

(llave,valor)=each(hash)
($llave,$valor)=each(%hash);
Nopodemoshastaestemomentodarejemplosdeesteoperadoryaqueimplicausar
mtodosqueannohemosestudiado.
Porestemotivo,dejaremoslaexplicacinconejemplosparaunapartemasadelante,enla
seccindeLainstruccinwhiledelsiguientecaptulo.

Pag.67

HugoMazaM.Perlbsicodesdecero

Pag.68

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO5

Estructurasdecontrol
Pag.69

HugoMazaM.Perlbsicodesdecero

Pag.70

Conejemplossencillosparaautomatizacindetareasenservidores

5.EstructurasdecontrolenPerl
AliniciodellibrohablamosdequeunscriptdePerlesunasuscecindeinstrucciones.
Estasinstruccionesseejecutanenordenunatrasotrahastaquetermineelscript.
Sinembargo,haymtodosdecontrolarelflujodeunscriptparaqueseejecutende
diferentesmaneraslasinstruccionesquetengamosalavista.
Unassi,otrasnosegnuncriterio,otrasmasdeformarepetitivahastaquesecumpla
algunacondicinestablecidapornosotrosyprosigamosconelcurso"normal"delscript.
ParacontrolarelflujodeunscripttenemosenPerlvariasestructurasparaesteefecto.
Bloquedeinstrucciones
LaprimeracosaquedebemostomarencuentaesquepodemosejecutarunBloquede
Instrucciones,elcualestdelimitadoporlossignosdellaves{}.
Ytodaslasinstruccionesdentrodeestebloqueseejecutanunaaunaensecuencianormal
comoseejecutanentodoelscript.
{

primera instruccin...
segunda instruccin...
...
ltima instruccin...

Estebloquedeinstruccionesesaceptadocomosifueraunasimpleinstruccin,estoes,
queseejecutaenelordendeunasimpleinstruccinsegnelordengeneraldelscript.
5.1Lafuncinif
Esunafuncinqueejecutaunbloquedeinstrucciones,mientrasunacondicinestablecida
seaevaluadayresulteverdadera.
Unacondicinverdaderatienequetenerunvalorbinariodiferentedecero(0).
Lasintaxiseslasiguiente:
Pag.71

HugoMazaM.Perlbsicodesdecero
if
{
}

( condicin = verdadero )
... Bloque de instrucciones a ejecutar (si condicin = verdadero).

Recodemosquepordefecto,enPerlunavariablevacatieneunvalorceroofalso,yen
casocontrario,siunavariablenoesigualavacoocero,esverdadero.
Vacio=>falso
0=>falso
novaco=>verdadero
diferentede0=>verdaddero
Lamismasintaxislatenemosvirtualmentedeestamanera:
if
{
}

( 1 )
... Bloque de instrucciones a ejecutar.

Dondeloquecolocamosdentrodelparntesisresultaserun1odiferentedecero,yalfinal
decuentas,verdadero.
Enperl,podremostenerdiferentesmanerasdeevaluarunacondicin.
Recordemoslosoperadoresrelacionalesdelaseccin4.1.2,loscualesevalanuna
expresinpararetornarunvalordefalsooverdadero.
Puesestosoperadorescumplensufuncinperfectadentrodelasfuncionescomoif.
Hagamosunpequeoejemplo:
#!/usr/bin/perl
$var = "";

# variable vaca = 0 = falso

if ( $var ne "" ) {
print $var, "\n";
}

# si $var "no es igual" a vaco

Enestecasonoseimprimeabsolutamentenada,yaquelacondicinesfalsa,porque$var
siesigualavaco.
Ahoraasignemosunvalora$var.
Pag.72

Conejemplossencillosparaautomatizacindetareasenservidores
#!/usr/bin/perl
$var = "Hola mundo...";

# variable no vaca

if ( $var ne "" ) {
print $var, "\n";
}

# si $var "no es igual" a vaco

Ahhhhh,ahorasiimprimimos"Holamundo..."
Recordemosunascuantaslneasatrs,dondedecamosquesepodrnejecutarlas
instruccionesdelbloquesitenemosunavalorverdadero,yqueunavariablenovacaes
igualaverdadero.
Podemoslamismainstruccinescribirlaas:
#!/usr/bin/perl
$var = "Hola mundo...";

# variable no vaca = 1 lgico = verdadero

if ( $var ) {
# si $var existe = diferente de 0 = verdadero
print $var, "\n";
}

Imprimiendo"Holamundo..."porquelaevaluacindelacadenaresultserdiferentede
cero(onovaco)overdadero.
Estonosponeapensar(sinonossalehumodenuestracabeza),quetalsideclaramos
nuestravariableconunvalordecadenaperoqueestaseacero:
#!/usr/bin/perl
$var = "0";

# variable escalar con contenido de caracter 0


# ojo! por las comillas no es un nmero, es una cadena

if ( $var ) {
# si verdadero o 1 lgico
print $var, "\n";
}

Resultcomopensamos,unescalardecaracter"0"esigualaceronumrico,osea,falso.
Nuestravariablesetransformadependiendodelcontextodondeseestusando,ysial
principiodeclaramoslavariableenuncontextoescalardecaracteres,elusoqueledamos
esalrededordeuncontextonumrico,porlotanto,lavariablevaleceronumricoofalso.
Enestecasonoimprimenada,niel"0"porquelacondicinevaluadadevuelve0ofalso,
Pag.73

HugoMazaM.Perlbsicodesdecero

anycuandolavariablenoestvacainicialmenteporelescalarasignado"0".
Sinembargo,sienlugardeasignarleunvalordeunsolocero,ledamosunvalordedoble
cerocomocadena,estenovaldr0,sinoqueyaesunacadenadetextonovaca.
Veamos:
#!/usr/bin/perl
$var = "00";

# variable escalar con contenido de caracteres 00


# ojo! Ya es una cadena de texto no vaca

if ( $var ) {
# si $var es cadena no vaca o 1 lgico
print $var, "\n";
}

Estosiimprimiralgo,elvalorde$varquees00yaquelavariable$varesunescalarno
vacoyporlotanto,igualaun1lgicoylaevaluacindevuelveverdadero,porloquese
ejecutaloqueestdentrodelbloquedeinstrucciones.
5.1.1Else
Ahora,quepasarasinosinteresaejecutarotrobloquedeinstruccionescuandola
condicinresultefalsa...
Estoes,siesverdadero,ejecutaesto,siesfalsoejecutaestootro...
Podremosusarlafuncinelseparaesteresultado.
Sintaxis:
if ( condicin = verdadero )
{
}

... bloque ejecutable si la condicin devuelve verdadero

else
{
}

... bloque ejecutable si la condicin no devuelve verdadero

Veamosunejemplo:
Pag.74

Conejemplossencillosparaautomatizacindetareasenservidores
#!/usr/bin/perl
$var = "";
if ( $var ) {
# si $var "no es igual" vaco o 0
print $var, "\n";
}
else
{
print "Nada que imprimir \n";
}

Estoimprimedesdeluego"Nadaqueimprimir"(yunsaltodelnea),porquelavariable
$varestabavacayseejecutaloqueseencuentredentrodelbloquesiguienteaelse.
Enlaprcticapodemoscolocarelcierredelprimerbloque,lafuncinelseylaaperturadel
segundo,enlamislalneaparaahorrarnosespacioenlneasylascosasseanmas
legibles:
#!/usr/bin/perl
$var = "Hola Mundo!!";
if ( $var ) {
print $var, "\n";
} else {
print "Nada que imprimir \n";
}

Imprimeconelejemploanterior,el"Holamundo!!"delavariable$var.

5.1.2Elsif
Cuandotenemosmuchasfuncionesif()subsecuentesyestnrelacionadas,esdecir,se
tienendosomasdiferentesopciones,podemosescribirloas:
if ( Condicion1 ) {
Bloque de instrucciones 1
cuando Condicion1 devuelve verdadero
} elsif ( Condicion2 ) {
Bloque de instrucciones 2
cuando Condicion2 devuelve verdadero
y Condicion1 devuelve falso
} elsif ( Condicion3 ) {
Bloque de instrucciones 3
cuando Condicion3 devuelve verdadero
y Condicion2 devuelve falso

Pag.75

HugoMazaM.Perlbsicodesdecero
} elsif ( Condicion4 ) {
Bloque de instrucciones 4
cuando Condicion4 devuelve verdadero
y Condicion3 devuelve falso
} else {
Bloque de instrucciones al devolver falso todo
}

5.1.3Sintaxiscasireal
Perlestdiseadoporunlingista,LarryWall,yesporestoquenuestrolenguajefavorito
escapazdesoportarestructurassintcticasmuyparecidasalaformacomohablamos
(bueno...eningls).
Lasintaxisdeif:
if
{
}

( condicin = verdadero )
... Bloque de instrucciones a ejecutar (si condicin = verdadero).

Esposibleescribirladeotraforma:
$var = "algo" if

condicin = verdadero

Ejemplo:
#!/usr/bin/perl
$var = "Hola Mundo!!";

# asignamos una cadena a $var

print "$var \n" if $var;

# se imprime $var si posee un valor

Estoimprimedesdeluego,HolaMundo(si$vartienevalor=verdadero).
Si$varnotienevalor,esdecir,valeuncerolgicoofalso,noseejecutalainstruccincon
lafuncinprint.
5.2Lafuncinunless
Ahora,quepasasinoqueremosejecutarnadacuandolacondicindevuelvaverdadero,
solocuandolacondicindevualvafalso.
Pag.76

Conejemplossencillosparaautomatizacindetareasenservidores

Enteoraseraas:
#!/usr/bin/perl
$var = "Hola Mundo!!";
if ( $var ) {

# si $var "no es igual" vaco o 0

# NO quiero hacer nada


} else {
print "Nada que imprimir \n";
}

Parasolucionaresto,existelafuncinunless,queejecutaunbloquedeinstrucciones
cuandolaevaluacindeunacondicindevuelvafalso.
Elmismoejemplousandolafuncincorrecta:
#!/usr/bin/perl
$var = "";
unless ( $var ) {
}

# si $var "es igual" vaco = 0 = falso

print "Nada que imprimir \n";

Notequepuedeserlocontrarioalafuncinif().
Cuandolavariableposeecontenidonoqueremoshacernada,asquesileasignamosun
valora$var,noimprimimosnada.Estoes,noseejecutarelbloquesiguienteaunless().
Porltimoagregamosqueunless()tambinposeecompatibilidadconelse.
Dejamosasupropiocriterioexperimentarconestoyusarloenlugardelafuncinif().
5.3Lafuncinwhile
ExistenenPerltambinunasfuncionesqueejecutanunbloquedeinstruccionesenforma
repetitiva,mientrasunacondicinseaverdadera.
Elbucleocicloserepiteindefinidamentehastaquelacondicindevuelvafalso.
Lafuncinwhile()essimpleyrequieredeunacondicinenigualformaqueif().
Pag.77

HugoMazaM.Perlbsicodesdecero

Sintaxis:
while ( condicin = verdadero ) {
... Se ejecuta este bloque una y otra vez
}

Ejemplo:
#!/usr/bin/perl
$cont = 0;
while ( $cont <= 10 ) {
print "El contador es: ", $cont, "\n";
$cont ++;
}

# recordemos el operador aritmtico


# de incremento del punto 4.1.1

print "Ya salimos del ciclo \n";


exit;

Enesteejemplovemosquecomenzamoselcicloconunvalordelavariable$contiguala
cero,yconcadavueltadelciclo,incrementamoselvalorde$contenuno,as$contvale1,
despus2,luego3,yashastaquevale10,enesecaso,lacondicinyaesfalsa,ywhile()
terminaelciclo,continuandoconelcursonormaldelscript.
Mientrasestosuscede,ejecutamoselbloquedeinstruccionesdentrodelasllavesacada
ciclodewhile,queenestecasosolorefierenaimprimirlamismavariable$cont,para
efectosdeanlisis.
Elresultadosiejecutamoselscriptseraalgocomoesto:
user@host # ./script.pl
El contador es: 0
El contador es: 1
El contador es: 2
El contador es: 3
El contador es: 4
El contador es: 5
El contador es: 6
El contador es: 7
El contador es: 8
El contador es: 9
El contador es: 10
Ya salimos del ciclo
user@host #

Pag.78

Conejemplossencillosparaautomatizacindetareasenservidores

Existeunacaractersticaquehacedewhileunbuclemuyespecial.
Yesquewhilepuederecorrertodaunalistadeelementos,aunquenoseaunalistade
array.
Delaexplicacinquedejamospendientedeloperadoreachdelpunto4.3.4,podremos
recorrerunoaunocadaparllavevalordeunHash.
Veamos:
#!/usr/bin/perl
%hash = (
# Declaramos nuestro Hash
'carro' => 'azul',
'moto' => 'roja',
'camion' => 'negro',
);
while ( ($llave, $valor) = each(%hash) ) {
print $llave . " == " . $valor . "\n";
}

# recorremos el Hash
# imprime cada par llave-valor

Elresultadoimpresoenlapantallaseralgoparecidoaesto:
user@host # ./script.pl
carro == azul
moto == roja
camion == negro
user@host #

Enotroaspecto,siacasodeclaramosartificialmenteverdaderalacondicinqueevala
while,elcicloseejecutarindefinidamentehastaquenocancelemoselprocesodelscript
desdeafuera.
Ejemplo:
#!/usr/bin/perl
$cont = 0;
while ( 1 ) {
print "El contador es: ", $cont, "\n";
$cont ++;
}

# recordemos el operador aritmtico


# de incremento del punto 4.1.1

print "Ya salimos del ciclo \n";

Pag.79

HugoMazaM.Perlbsicodesdecero

Estebuclenuncavaaimprimirelyavisto:Yasalimosdelciclo,puestoquenuncasaledel
bucle,ademsdequelosincrementosseharnhastaelinfinito.
SiestamosenGNU/Linux,conoprimirlasteclascontrol+Ccancelamoselprocesoactual,
saliendodelscriptcompleto.
5.4Lafuncinfor
Otrobuclequeseejecutaiterativamentemientrasunacondicinseaverdadera,esfor()
Sintaxis:
for ( inicio; condicin; incremento ) {
intruccin_1;
intruccin_2;
intruccin_3;
}

Regresandoalbuclewhile()delpuntoanterior:
#!/usr/bin/perl
$i = 0;
while ( $i <= 10 ) {
print "El contador es: ", $i, "\n";
$i ++;
# recordemos el operador aritmtico
# de incremento del punto 4.1.1
}
exit;

Estomismolopodemosescribirconfor()delasiguientemanera:
#!/usr/bin/perl
for ($i = 0; $i <= 10; $i++) {
print "El contador es: ", $i, "\n";
}
exit;

Usandomenoslneas,imprimimosexactamentelomismoqueconelusodewhile.
Nodebehacerfaltaexplicacionesparaestafuncin,ysiesas,creoquedebemosrepasar
denuevoloquellevamosdellibro.
Eloperadorfor()tambinescapazdeprocesarunalistacomowhile():
Pag.80

Conejemplossencillosparaautomatizacindetareasenservidores
#!/usr/bin/perl
for $i ( 0 .. 9 ) {
print $i, "\n";
}

# rango del 0 al 9
# imprime del 0 al 9 con salto de lnea

exit;

Peroparaesteusomascompletoexistelafuncinforeach(),queveremosacontinuacin.

5.5Lafuncinforeach
Laconstruccinforeach()recorreiterativamentecadaelementodeunalistadada.
Lasintaxisloexplicabien:
foreach $elemento ( de, la, lista, de, elementos ) {
bloque de instrucciones...
}

Unejemplosimple:
#!/usr/bin/perl
@a = (1,2,3,4,5);
foreach $i ( @a ) {
print $i, "\n";
}

Lafuncinforeach()escapazdealterarcadaelementodelalistacuandolarecorre.
#!/usr/bin/perl
@a = (1,2,3,4,5);
foreach $i ( @a ) {
$i *= 3, "\n";
}

# ahora @a = (3, 6, 9, 12, 15)

5.6Lafuncinuntil
EstafuncinespocovistaenPerl,sinembargonoesmenosimportantequelasdems,ya
quetodoenPerltieneaplicacionesespecficas.
Ejecutaunbloquedeinstruccionesmientraslacondicinresultefalsa.Es,aparentemente,
Pag.81

HugoMazaM.Perlbsicodesdecero

locontrariodewhile(),saliendodelbuclecuandolacondicinregreseverdadero.
Sintaxis:
until ( Condicin = falso ) {
Bloque de instrucciones...
}

Conunejemploloilustramos:
#!/usr/bin/perl
$i = 0;
until ( $i >= 10 ) {
# mientras $i no sea igual o mayor a 10
print "El contador es: ", $i, "\n";
# se imprime $i
$i ++;
# incremento de 1
}
exit;

Estoimprimirdel0al9porque$i=10yadevuelvefalsoalafuncin.
5.7Bifurcacionesparalosbucles
Enalgunosmomentosdesearemosteneruncontrolunpocomasestrictodeloquepase
dentrodeunafuncin.
Supongamosquetenemosunarraydemasde100,000elementosobtenidosdecualquier
partedeunservidor,ydebemosencontrarsialgunodeloselementoseselquebuscamos.
Quetalsiencontramoselelementoconelndice225...Tendremosqueesperaraqueel
buclerecorraelrestodeloselementosparacontinuarconelscript?
Larespuestaesno,haymtodosparasalirdeunbucleociclo,ascomoparacontinuar
conl.
5.7.1Lasalidalast
Saledefinitivamentedeunbucle.Marcaelcicloactualcomoelltimo.

Pag.82

Conejemplossencillosparaautomatizacindetareasenservidores

Ejemplo:
#!/usr/bin/perl
$i = 0;
while ( $i <= 10000 ) {
print $i, "\n";
$i ++;
if ( $i == 10 ) {
last;
}
exit;

# se inicia el ciclo hasta 10,000


# recordemos el operador aritmtico
# de incremento del punto 4.1.1
# salimos del bucle cuando $i = 10
# No esperamos a que pasen los 10,000

Estoimprimedel0al9,porquecuando$iseaiguala10,saledelbuclesinesperaraque
serealiceotrociclodebidoalabifurcacinlast.

5.7.2Lafuncinnext
Locontrariodelast,nextcontinuaconelciclo.
Estafuncinestimplcitaencualquierbucle,soloqueenocasionespuedesernecesario
declararloexplcitamentepornecesidadesespecficasdelscript.
Ejemplo:
#!/usr/bin/perl
$i = 0;
while ( $i <= 10000 ) {
print $i, "\n";
$i ++;
if ( $i == 10 ) {
last;
} else {
next;
}
exit;

# recordemos el operador aritmtico


# de incremento del punto 4.1.1
# salimos del bucle cuando $i = 10
# No esperamos a que pasen los 10000
# aprendamos como funciona
# talvez lo necesitemos

Haceexactamentelomismoqueelejemploanterior.

Pag.83

HugoMazaM.Perlbsicodesdecero

5.7.3Etiquetas
Hayocacionesenquedebamostenerunbucledentrodeotrobucle,porejemplo,unciclo
whiledentrodeuncicloforeachoviceversa.
Sinembargodentrodelbucleinteriorcolocamosunafuncinifparapodersalirnosolodel
bucleinterior,sinotambindelbucleexterno.
Comolastsolosaledelbucledondeest,esnecesariocolocaretiquetaspara"marcar"la
instruccinparahacerunareferenciadeespacio.
Lasetiquetasnotienenningnprefijoespecialdepuntuacin,soloseescriben.
Aspodremosusarlafuncinlastdestinandolasalidadelbuclemarcadoporlaetiqueta:
last ETIQUETA;

Ejemplosimple:
ETIQUETA: while (condicin = 1) {
instruccin;
instruccin;
instruccin;
if (condicin adicional) {
last ETIQUETA;
}
}

Ejemplocompuesto(desdeLearningPerl):
#!/usr/bin/perl
EXTERNO: for ($i = 1; $i <= 10; $i++) {
INTERNO: for ($j = 1; $j <= 10; $j++) {
if ($i * $j == 63) {
print "$i veces $j es igual a 63!\n";
last EXTERNO;
}
if ($j >= $i) {
next EXTERNO;
}
}
}
exit;

Elprimerbuclerecorreiterativamentelosnmerosdel1al10yelsegundolohace
igualmente,porloquelasmultiplicacionesde$i*$jcomienzandesde(1,1),(2,1),(2,2),
(3,1),(3,2),(3,3),(4,1),yassucesivamentehastaencontrarlacombinacinexactacuyo
Pag.84

Conejemplossencillosparaautomatizacindetareasenservidores

resultadosea63(7*9)yentonces,salenosolodelbucleinterno,sinotambindelbucle
externoparanoejecutarelrestodelosciclos,pormediodelainstruccin:
last EXTERNO;

Siejecutamoselscriptdebeimprimiralgoparecidoaesto:
user@host:# ./test.pl
9 veces 7 es igual a 63!
user@host:#

Pag.85

HugoMazaM.Perlbsicodesdecero

Pag.86

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO6

Expresionesregulares
Pag.87

HugoMazaM.Perlbsicodesdecero

Pag.88

Conejemplossencillosparaautomatizacindetareasenservidores

6.Expresionesregulares
Unaexpresinregularesunmecanismoquebuscaunpatrndentrodeunacadenade
texto.
LasexpresionesregularessonusadaspormuchosprogramascomoloscomandosdeUnix
grep,sed,awk,ed,vi,emacs,etc,ycadaprogramadesdeluegotienesusvariantesensu
sintaxis.
EnPerl,podemosdelimitarunaexpresinregulargeneralmenteencerrandolaolas
cadenasentreslashesobarrasinclinadas:
/cadena/
Yestosignificaquedentrodelacadenadada,queremosencontrarelpatrnindicado
dentrodelosslashes.
6.1Expresionesregularesdecomparacin
Laformadeusomasbsicadelasexpresionesregularesesprecisamentelacomparacin,
ysetratadeencontrarunacadenadentrodeotra.
Paraestousamossiemprelasintaxis:
$cadena =~ /patrn/;

Usandoelsignodeigualseguidodeuntilde.
Veamosunejemploenunscript:
#!/usr/bin/perl
$datos = "Cristobal Colon descubri Amrica";
if ( $datos =~ /Colon/ ) {

# Buscamos "Colon" dentro de $datos


# y devuelve verdadero si lo contiene

print "Si contiene \"Colon\" \n";

# no olvidemos el \ para las "

} else {
print "No contiene \"Colon\" \n";
}

Pag.89

HugoMazaM.Perlbsicodesdecero

Estodesdeluego,imprimeSicontiene"Colon".
Sibuscamosqueunacadenacontengaporejemplo,unsemicolon(;),esnecesariousar,
comosiempre,elbackslash:
$datos =~ /hola\;/;

Paranoconfundirloconelsemicolondelfinaldeinstruccin.
Haysmbolosquerepresentandiferentescosasalasdelcaracterespecfico,ysonlos
caracteresreservados:
* + $ ^ | [ ] ( ) { } - . \w \s \d \n \

Elasteriscoseusaparabuscaruncaracterrepetidodentrodeunacadena,ycomomnimo
debeencontrar0ocurrenciasdelmismo,esdecir,puedequehaya,puedequeno...8{D
$cdn =~ /ab*c/;

Enestaexpresinbuscamos:
Primerouncaractera,seguidodeb'smnimocerohastanveces,yseguidodeunac.
Labnoesindispensablequeexistaenlacadena:
#!/usr/bin/perl
$abc = "ac";

# podemos poner $abc = "abbbc" o $abc = "abc"

if ( $abc =~ /ab*c/ ) {
print "S contiene ac, o abc, o abbbc \n";
}
exit;

Silabfueraindispensablequeexistaenlacadena,usaremoselsigno+:
#!/usr/bin/perl
$abc = "ac";

# podemos poner $abc = "abbbc" o $abc = "abc"

if ( $abc =~ /ab+c/ ) {
# si contiene una o mas b's
print "S contiene abc, o abbbc \n";
} else {
print "No contiene abc, o abbbc \n";
}
exit;

Pag.90

Conejemplossencillosparaautomatizacindetareasenservidores

Enestecasolepedimosalaexpresinquenosdevuelvaverdaderosiencontramosun
caractera,seguidodeb'smnimounahastanveces,yseguidodeunac.
Elresultadoalimprimirser:Nocontieneabc,oabbbc.
Ahora,cuandoelpatrnbuscadodebeestareliniciodelacadena,usaremoselsignode^:
#!/usr/bin/perl
$abc = "abcxyz";
if ( $abc =~ /^abc/ ) {
# buscamos al inicio de la cadena
print "S contiene abc al inicio \n";
} else {
print "No contiene abc al inicio \n";
}
exit;

EstoimprimirSicontieneabcalinicioporqueelpatrnbuscadosseencuentraal
principiodelacadena$abc.
Ysideseramosbuscarelpatrnalfinaldelacadena,enestecasousaremosel$alfinal
delpatrnbuscadoparaindicarnuestrosdeseos:
#!/usr/bin/perl
$abc = "abcxyz";
if ( $abc =~ /xyz$/ ) {
# buscamos al final de la cadena
print "S contiene xyz al final \n";
} else {
print "No contiene xyz al final \n";
}
exit;

YclaroqueimprimirScontienexyzalfinal,porqueeselpatrnquebuscamosystese
encuentraalfinaldelacadena$abc.
Yquetalsiqueremosunacosaolaotra?
Enestecasousaremoseloperadorbooleanoor,queennuestrasexpresionesregulares
tienelasintaxis:
/uno|otro/

As,nuestroejemplolopodemosmodificaryexplicarlocomo:sicontieneabcaliniciooxyz
Pag.91

HugoMazaM.Perlbsicodesdecero

alfinaldelacadena...:
#!/usr/bin/perl
$abc = "abcdefghijklmnopqrstvwxyz";
if ( $abc =~ /^abc|xyz$/ ) { # buscamos al inicio o al final de la cadena
print "S contiene abc al inicio, o xyz al final \n";
} else {
print "No contiene abc al inicio, o xyz al final \n";
}
exit;

Alejecutarelscriptnosimprime:Scontieneabcalinicio,oxyzalfinal,queesloque
buscbamos.Secumplenambascosas.
Cuandotengamosqueespecificarunrangodecaracteres,podremoshacerusodelos
corchetes,[abc]significara:cualquiercaracterentrea,boc,esdecir,puedenser
cualquieradeestostres...solouno.
Ejemplo:
#!/usr/bin/perl
$abc = "abcdef";
if ( $abc =~ /[aqz]/ ) {

# buscamos a, q o talvez z

print "S contiene a, q z \n";


} else {
print "No contiene a, q z \n";
}
exit;

Enestescript,comolacadenacontienecualquiercaracteraescogerentrea,qz,se
imprimeScontienea,qz.
Sia$abclequitamoslaaylacambiamosporgoz,darelmismoresultado,cuandola
cadenanocontenganingunodeestostrescaracteres,devolverfalso.
Tambinpodemosespecificarunrangocompletomedianteelusodelguin:

Pag.92

Conejemplossencillosparaautomatizacindetareasenservidores
#!/usr/bin/perl
$abc = "abcdef";
if ( $abc =~ /[a-zA-Z]/ ) {

# buscamos rangos, de la "a" a la "z"


# minscula o mayuscula
print "S contiene desde a hasta la z \n";

} else {
print "No contiene desde a hasta la z \n";
}
exit;

AquseimprimeScontienea,qz,porqueestamosbuscandocualquiercaracterentrela
aylazytambinentrelaAylaZdentrodelacadena$abc.
Otrosoperadoresdeexpresionesregularesson:
\w=cualquiercaracteralfanumricoyelguinbajo
\s=unespacio
\d=dgitos(nmeros)
\n=saltodelnea
\t=tabulacin
\r=retornodecarro
\f=saltodepgina
.=cualquiercosa
Ejemplosvarios:
Siqueremosencontrarcuaquiervocal:
/[aeiouAEIOU]/

Estolopodemosescribirdeestaotraforma:
/[aeiou]/i

Notealfinaldespusdelslashdecierrequeusamoslaletrai,estoparadecirlealas
expresionesregularesquenonosimportasiesmaysculaominscula.
Cualquierdgito:
/[1234567890]/

Pag.93

HugoMazaM.Perlbsicodesdecero

Estolopodemosescribirmasfcilmenteas:
/[0-9]/

# es un rango del 0 al 9, cualquier dgito

Cualquierletraodgito:
/[a-zA-Z0-9]/

# son rangos, cualquier letra o dgito.

Cualquierconjuntode...unespacio,luegoletrasodgitos,ydespusotroespacio:
/\s[a-zA-Z0-9]\s/

Elconjuntode...lacantidadqueseadeespacios,seguidodeletraodgito,ydespusotro
espacio:
/\s+[a-zA-Z0-9]\s/

Noteelsignode+paradeclararquesonunoomasespacios.
Elconjuntode...espacios(lacantidadquesea),letrasodgitos(lacantidadquesea),y
despusotrosespacios(lacantidadquesea):
/\s+[a-zA-Z0-9]+\s+/

Loquesea,lacantidadquesea:
/.*/

Lasletrasabc,seguidasdecualquiercosa,ydespusxyz:
/abc.*xyz/

Equivalenciasentrecaracterespredefinidosypatronescreados:
\w = [a-zA-Z0-9_]
\s = [ ]
\d = [0-9]

Usandoundelimitadordiferente.
Cuandonoqueremosconfundirnosconlosslashes(aplicandoelbackslash),porejemplo:
Pag.94

Conejemplossencillosparaautomatizacindetareasenservidores
/^\/usr\/etc/

Esmejorcambiareldelimitador(aquusamos!enlugardelslashtradicional):
m!^/usr/etc!

Ocualquierotro(ahorausamos#):
m#^/usr/etc#

Notelamantesdecomenzareldelimitadorespecial(dematch).

6.1.1Memoriadelasexpresiones
Dentrodelasexpresionesregulares,podremosencerrarentreparntesisalgunosgrupos
decadenaslascualesdeseamosusaroextraerparaprocesarlasposteriormente.
Estaspequeaspartesretenidasenlamemoriadelaexpresin,laspodemosllamar
posteriormentecomovariablesespeciales,sucesivamente:$1,$2,$3...$n.
Ejemplo:
#!/usr/bin/perl
$var = "La vuelta al mundo en 80 das";
$var =~ /\w+\s([a-zA-Z]+)\s.*/;
$palabra1 = $1;

# $1 es lo que est entre parntesis: ([a-zA-Z]+)


# cualquier cantidad de letras maysculas o minsculas
print $palabra1, "\n";
# imprime: vuelta

Siextraemosmascadenasmemorizadas:
#!/usr/bin/perl
$var = "La vuelta al mundo en 80 das";
$var =~ /^[a-zA-Z]+\s([a-z]+)\s\w*\s([a-z]+)\s.*/;
$p1 = $1;
$p2 = $2;

# es lo que est en el primer parntesis


# el segundo parntesis

print $p1 . " " . $p2 . "\n";

# imprime: vuelta mundo

exit;

Pag.95

HugoMazaM.Perlbsicodesdecero

Ahorapodemosusartodosestosdatosparaejemplificaryresolverunpequeoproblema.

Problema:
MedianteelcomandoUnixhostdominio,podemossaberlaIPdeunnombrededominio
cualquiera.
DebemosextraerlaIPdeldominiogoogle.com.
Sienlneadecomandosejecutamos:
user@host # host google.com

Nesdevuelvealgoas:
user@host:# host google.com
google.com has address 74.125.45.100
google.com has address 74.125.67.100
google.com has address 209.85.171.100
google.com mail is handled by 10 smtp1.google.com.
google.com mail is handled by 10 smtp2.google.com.
google.com mail is handled by 10 smtp3.google.com.
google.com mail is handled by 10 smtp4.google.com.
user@host:#

(Raro,no???)

Entesdeproseguir,explicaremoscomointeractaPerlconcomandosdelsistema
operativo.
ExistenalgunasmanerasdeejecutaruncomandodelOSytomarelresultadoenuna
variable.
Primermtodo,lafuncinsystem:
$resultado = system("ls -lrt");

Enestecomandosimplementelistamoselcontenidodeldirectorioactual.
Segundomtodo,elapstrofe(`):
$resultado = `ls -lrt`;
print $resultado, "\n";

RecordemosqueestelibroestenfocadoainteractuarconServidoresdealtorendimiento
Pag.96

Conejemplossencillosparaautomatizacindetareasenservidores

porloqueasumimosquestosusanalgnsabordeUnixoGNU/Linux.
Regresemosanuestroproblemaoriginal,lasalidadelcomandohostnosservirpara
analizarlaslneasdesalidaygenerarnuestrocdigo:
#!/usr/bin/perl
$cmd = `host google.com`;

# mecanismo de ejecucin de un comando


# a nivel del Sistema Operativo: `command`.

@arrayCmd = join(/\n/, $cmd);

# separamos cada lnea y las colocamos


# como elementos de un array

# ahora analizamos el array en un bucle y buscamos patrones de IP's:


foreach $i ( @arrayCmd ) {

# por cada elemento $i del array @arraycmd...

if ( $i =~ / has address / ) {

# si contiene esta cadena, tiene la IP

$i =~ /.*\s([0-9\.]+)\s.*/;
my $ip = $1;

# buscamos el patrn que contenga


# solo nmeros y puntos (IP's)
# asignamos el primer (y nico) memorizado a $ip

if ( $ip =~ /[0-9\.]+/ ) {
# podemos re-asegurarnos del formato IP
print "La IP es: " . $ip . "\n";
last;
# solo la primer secuencia de IP
}

exit;

Alejecutarelscriptnosdebeimprimiralgocomoesto:
user@host:# test.pl
La IP es: 74.125.45.100
user@host:#

Ustedliteralmentepuedetranscribirestetextoaunarchivoejecutable(conpermisos755)
desuequipoServidorconSOUnixoGNU/Linuxydebetrabajarperfectamenteparasu
anlisis.
Aestasalturasdellibro,deberamosentendercadainstruccin,nohemosusadonadaque
nohallamosvisto.

Pag.97

HugoMazaM.Perlbsicodesdecero

Otroproblema:
Debemosanalizarlossistemasdearchivosdeldiscoduroparaverquealgunonoestpor
encimadeunumbralquedefinamosdeantemano.
Planteamiento:
PormediodelcomandoUnixdfkpodemosvisualizarlalistadesistemasdearchivosdel
disco.
ElsistemadearchivosdeldiscodurodeunaPCconUbuntu(GNU/Linux):
hmaza@hmaza:~$ df -k
S.ficheros
Bloques de 1K
Usado
/dev/sda1
12389324
3682040
tmpfs
252796
0
varrun
252796
344
varlock
252796
0
udev
252796
2764
tmpfs
252796
172
lrm
252796
2004
/dev/sda3
25238332 17717400
hmaza@hmaza:~$

Dispon Uso% Montado en


8077940 32% /
252796
0% /lib/init/rw
252452
1% /var/run
252796
0% /var/lock
250032
2% /dev
252624
1% /dev/shm
250792
1% /lib/modules...sigue
6248988 74% /home

Anlisis:
a)Nosinteresalosporcentajesdeuso,eslaquintacolumna.Contieneelsignode%.
b)Obviamente,soloanalizolossistemasdearchivosqueyoelija:
/dev/sda3(solounoestabienporahora).
c)Sipasade80%(porejemplo)debeimprimir(nohemosaprendidomasqueimprimir)
algoquemeindiqueunaalarma.
#!/usr/bin/perl
####################################################
#### VARIABLES DE CONFIGURACION:
# maximo porcentaje admitido sin alarmar (umbral)
$max = 80;
# sistema de archivos a monitorizar
$sisdev = "/dev/sda3";
####################################################
$comando = `df -k`;

Pag.98

# cargamos las lneas del comando a una variable

Conejemplossencillosparaautomatizacindetareasenservidores
@lns = split(/\n/, $comando);

# separamos cada lnea y las colocamos


# como elementos de un array

foreach $linea ( @lns ) {

# por cada $linea del array @lns

if ( $linea =~ /$sisdev/ ) {

# si contiene el sistema
# de archivos deseado...

$linea =~ /.*\s([0-9]+)\%\s.*/;
$valor = $1;

# buscamos la columna y
# extraemos el valor

if ( $valor >= $max ) {

# comparamos el valor
# con el umbral

print "Alarma!: $sisdev en $valor\%. Igual o por


encima del umbral de $max\% \n";

exit;

Sinotamosque/dev/sda3tieneun74%deusoyelumbralesde80,estescriptnovaa
imprimirnada.
Todoestbien.
Sinembargopodemosbajarelumbralparaquenosmuestrealgoquenoshagasentir
felicesalejecutarelscriptyquenosavisequealgoandamal.
Podemoscambiarelumbralhastadondedeseemos,enestecaso,pondremoslavariable
$maxconunvalorde70,deestemodo,comoelsistemadearchivos/dev/sda3tieneun
porcentajedeusodel74,alejecutardenuevoelscript,nosdebeimprimiralgocomoesto:
hmaza@hmaza:~$ test.pl
Alarma!: /dev/sda3 en 74%. Igual o por encima del umbral de 70%
hmaza@hmaza:~$

6.2Expresionesregularesdesustitucin
Lasexpresionesregularespuedenservirnosparasustituircadenasdecaracteres.
Laexpresinbsicaes:
s/Cadena_Anterior/Cadena_Nueva/opciones;

Pag.99

HugoMazaM.Perlbsicodesdecero

ReemplazalaCadena_AnteriorporlaCadena_Nuevaenunaexpresin.
Ejemplo:
$var = "Hola Mundo";
$var =~ s/Hola/Adis/;

# sustituimos la palabra Hola por Adis

print "$var \n";

# esto imprime: Adis Mundo

Otroejemplo,ahoraconopciones:
$var = "Esta es una prueba";
$var =~

s/(\w+)/<$1>/gi;

print "$var

\n";

# imprime:

<Esta> <es> <una> <prueba>

Variascosasqueaprender:
Usamoslasopcionesgi,lascualessignifican:lag,quedebamossustituirenforma
recursiva,ylai,quenonosinteresasisonmaysculasominsculas.
Otracosacuriosa,peroqueyaaprendimos,losparntesismemorizaronlavariable$1,la
cualesusadaenlasustitucin,estoes,lareusamosdentrodelamismaexpresin.

Pag.100

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO7

Funcionespropias,subrutinas
Pag.101

HugoMazaM.Perlbsicodesdecero

Pag.102

Conejemplossencillosparaautomatizacindetareasenservidores

7.Funcionespropias,subrutinas
Unafuncinpropia,esllamadamascomnmentesubrutina,osolosub,yesdefinidaen
Perlporlasiguienteconstruccin.
sub nombre {
instruccin_1;
instruccin_2;
instruccin_3;
}

Unejemplodelfamosoholamundo:
#!/usr/bin/perl
sub hola {
print "Hola mundo\n";
}

Siescribimosunscriptconsoloestaslneasnohacenada,pueslasubrutinanoseinvoca
desdeningnlado.
Invocarunasubrutinaes"llamar"alafuncinpropiaparaejecutarla.
Bsicamenteesas:
subrutina();

LosparntesisleindicanaPerlqueesunafuncinpropialaqueseestinvocando.
Sinusarlosparntesis,podemosinvocarunasubrutinadeestaotraforma:
&subrutina;

Sialanteriorscriptusamosunllamadoalasubrutina...
#!/usr/bin/perl
hola();
exit;

# llamamos a la subrutina "hola"


# salimos del programa

sub hola {
print "Hola mundo\n";
}

Pag.103

HugoMazaM.Perlbsicodesdecero

Ahorasidebeimprimir:
user@host: # test.pl
Hola mundo
user@host: #

Noimportalaposicindelasubrutinadentrodelprograma,puedeinclusoestaralfinalde
todoelscript,Perlsabedeellaylaejecutacuandounolainvoque.
7.1Lavariableespecial@_
Antesdeproseguir,debemoshacerunaescalatcnica(ynomerefieroadesahogar
nuestraspenasodeshechoscorporales)parahablaracercadeunadelasvariables
especialesdePerl.
Elarregloespecial@_estimplcitosiempre,dentrodecualquierscriptdePerl,aunqueno
ladeclaremosqueexiste,stasiempreexiste.Vivefelizennuestroprograma.
Lavariable@_poseecomotodoarray,elementosindizados,yestoslospodemosllamarde
laformacomn:
$_[0], $_[1], $_[2], ... $_[n]

Unejemplodeutilizacinenunbucle:
#!/usr/bin/perl
@array = qw(Juan Pablo Pedro);
foreach ( @array ) {
print $_ , "\n";
}
exit;

Noesquesenoshallaolvidadoescribir:
foreach $linea ( @array ) {

Nonecesitamosdesignarunavariableespecialmenteparaasignarrecursivamenteelvalor
decadaelemento,porquePerlasignaesevaloralavariableespecial$_,lacual
imprimimos.
Pag.104

Conejemplossencillosparaautomatizacindetareasenservidores

Elarray@_ysuselementos$_[n]estarnvacoshastaquenolasusemoscomoeneste
ejemploqueacabamosdever.
Lavariable@_siempreeslocal,ysedestruyecuandosalimosdelbucle,sinembargolas
variableslocalesyglobaleslasestudiaremosunpoquitomasadelante.
Ylomismosucedeconlosdemsbuclescomowhile,foreinclusodentrodeunafuncin
propia,comoveremosacontinuacin.
7.2Argumentosdeunafuncinpropiaosubrutina
Parapasarargumentosenformadedatosaunasubrutina,usamoslosparntesisdela
mismasintaxis:
subrutina("Argumento1", "Argumento2", "Argumento3");

Notequelosargumentosquelepasamos,formanunalista,estoes,unalistade
argumentos,quepuedeserencualquiercaso,unarray,yaqueunarrayesunalistade
elementos:
subrutina( @argumentos );

Yademscadaargumentopuedeserunavariable:
subrutina($arg1, $arg2, $arg3);

Aspodremosusarlassubrutinaspasndolelosargumentosnecesariosparaqueestas
puedanusarlosparasutratamiento.
subrutina($carro, $moto, @animales, 32, 45);

EnestecasoPerlaplanaloselementosdelarrayyocurreunainterpolacindevariables,
haciendoqueloselementosdelarrayseenvenalasubrutinaenelmismoordendelos
ndicesdelarray,ydentrodelordendelasvariablesdelalistadeargumentos.
7.3Variablesglobalesylocales
Cuando"creamos"unavariableenunscript,estavariableexisteenformapredefinida,en
todoelscript,ylapodremosusardentrodeunasubrutinaodeunbuclesinproblemas.
Pag.105

HugoMazaM.Perlbsicodesdecero

Estoes,creamosvariablesglobales.
Cuandousamosunbucleounasubrutinaydeseamosqueunaotodaslasvariablesnose
usenfueradelasubrutina,oalsalirdeunbucle,podemosdeclararvariableslocales.
Paraestousamoslafuncinmy:
Ejemplodefuncionamiento:
#!/usr/bin/perl
$cosa = "carro";
$animal = "gato";
$numero = 45;

# $cosa es variable GLOBAL

@array = ($cosa, $animal, $numero);


foreach my $cosa ( @array ) {
# $cosa es variable LOCAL
print $cosa, "\n";
}
# $cosa local se destruye al terminar el bucle
print $cosa, "\n";

# se imprime la variable global $cosa = carro

exit;

Estoresultaenlaimpresinde:
user@host: # test.pl
carro
gato
45
carro
user@host: #

Hayquehacernotar:
Declaramosunavariable$cosaquesecrecomovariableglobal.
Declaramosunavariable$cosaparaelbucleforeachlacualsecrecomovariablelocal,
medianteelusodelafuncinmy.
Cuandocreamosunavariablelocal,Perldestruyeestacuandoelbucleolasubrutina
terminadeejecutarse.
Raznporlacual,pudimosimprimirlavariable$cosaalfinalyresultserquetieneelvalor
"carro"queledimosaliniciodelscript,ynoelvalor45,quefuelltimovalorqueseledi
enelbucleforeachsiestafueravariableglobal.

Pag.106

Conejemplossencillosparaautomatizacindetareasenservidores

Enlassubrutinas:
#!/usr/bin/perl
hola();
sub hola {
my $mundo = "Hola mundo";

print $mundo, "\n";

print $mundo, "\n";

# creamos la variable local la cual


# se destruye al final de la subrutina
# imprimimos la variable local

# no imprime mas que el salto de lnea, ya que


# no existe la variable global $mundo

exit;

Estoimprime:
user@host: # test.pl
Hola mundo
user@host: #

Notequesoloseimprimeelsaltodelneaalfinal.Yaquelavariable$mundoque
pretendemosimprimirfuunavariablelocaldelasubrutinaholayporlotantofudestruida
alfinalizaresta.
As,$mundonoexistecomovariableglobalysoloseimprimeelsaltodelneadela
segundafuncinprintqueusamos.

7.4Captandolosargumentos
Ahoravamosausarloqueacabamosdeaprenderparacaptarlosvaloresqueselepasan
aunasubrutinacomovalores,paratrabajarconellos.
Recordemoselapartado7.1endondemencionamosque:
Lavariable@_enunbuclesiempreeslocal,ysedestruyecuandosalimosdel.
Tambinrecordemoselusodelafuncinshift,lacuallequitaelprimerelementodeun
arrayyloretorna.
As,paraquitarleelprimervaloralavariableespecial@_tambinpodemosusarshiftpara
Pag.107

HugoMazaM.Perlbsicodesdecero

saberdeloselementos:
my $var = shift(@_);

Osimplemente:
my $var = shift;

# Perl sabe que nos referimos a la variable especial

Yaquesabemosque@_estimplcitadentrodelscriptytambindentrodecualquierbucle
osubrutinacomoarraylocal,ynonecesitamosdecirquenosreferimosa@_.
Veamosunejemplo:
#!/usr/bin/perl
hola("Hola mundo");
sub hola {
my $mundo = shift;

print $mundo, "\n";

# creamos una variable local quitando el primer


# elemento de la variable especial @_
# imprimimos la variable local

exit;

Igualmente,paracaptarlosdemsargumentos,siloshay,podemosusarelmismomtodo
paratomardeunoporuno,cadaelementodelarrayespacial@_:
my $uno = shift;
my $dos = shift;
my $tres = shift;

Igualmentepodemosusarloselementosdelarraydelaformaconvencional:
#!/usr/bin/perl
hola("Hola mundo");
sub hola {
my $mundo = $_[0];

}
exit;

Pag.108

print $mundo, "\n";

# creamos una variable local llamando al primer


# elemento de la variable especial @_
# imprimimos la variable local

Conejemplossencillosparaautomatizacindetareasenservidores

Ycadaelementodelarray,sihaymasdeuno:
my $uno = $_[0];
my $dos = $_[1];
my $tres = $_[2];

7.5Retornandolosresultados
UnasubrutinaenPerldebeprocesarlosdatosqueselepasancomoargumentosyeste
procesodebegenerarunresultado.
Esteresultadopuedeserdevueltoporlasubrutinaparaserprocesadaporelrestodel
script.
Paraestoseusalafuncinreturn.
Ejemplo:
sub multi {
my $var = shift;
$var .= " mundo";
}

return $var;

# concatenamos algo a la variable captada


# regresamos el valor que queramos

Deestamaneraalterminarlasubrutina,estanosregresaunvalor,comosisetratareuna
variablesimple.
sub multi {
my $var = shift;
$var .= " mundo";
return $var;
}

# concatenamos algo a la variable captada


# regresamos el valor que queramos

$result = multi("Hola");

# llamamos la funcin "multi" pasndole un


# argumento, la cadena "Hola"
# y tomamos lo que nos retorn la sub

print $result, "\n";

# imprime: Hola Mundo

7.6Uniendotodo
Ahoraveamoscomounirtodoparahacerlascosasmasfuncionales.
Pag.109

HugoMazaM.Perlbsicodesdecero

Hagamosunejemplo:
#!/usr/bin/perl
($hola, $num) = hola("Hola", 30);

# generamos una lista con las


# variables que regresa la subrutina.
# Sern variables globales

print "La cadena: " . $hola . "\n". "y el nmero: " . $num ."\n";
sub hola {
my $hola = shift;
my $num = shift;

# captamos el primer argumento


# captamos el segundo argumento

$hola .= " mundo";


$num += 10;

# concatenamos
# sumamos

return ($hola, $num);


}

# y retornamos una lista, que al


# final de cuentas es un array

exit;

Unasubrutinapuededevolvertantounasolavariable,ounalistadeellas,yenestecaso
podremosasignarloaunarray,comoenelejemplosiguiente:
#!/usr/bin/perl
@datos = hola("Hola", 30);

# genermos un array del retorno de la sub

print "La cadena: " . $datos[0] . "\n". "y el nmero: " . $datos[1] ."\n";
sub hola {
my $hola = shift;
my $num = shift;

# captamos el primer argumento


# captamos el segundo argumento

$hola .= " mundo";


$num += 10;

# concatenamos
# sumamos

return ($hola, $num);


}

# y retornamos una lista, que al


# final de cuentas es un array

exit;

Cuandounasubrutinadevuelveunnicovalor,estepuedeserasignadoaunavariable
escalaras:

Pag.110

Conejemplossencillosparaautomatizacindetareasenservidores
$var = subrutina(40, 30, 55);
sub subrutina {
instruccion1;
instruccion2;
return $valor;

Porquedevolviunavariabledeltipoescalar,nounalistadeellas.
7.7Variablessemilocales
Perlescapazdegenerarvariableslocalesquepuedanserusadassolamentedentrodeesa
subrutinaydentrodealgunassubrutinasqueseancolocadasdentroesasubrutinainicial.
Loexplicamos,sicreamosunasubrutina,ydentrodeestacreamosotrasubrutina,
podremosdeclararunavariablelocalparalasubrutinaexterna,peroglobalparalaolas
subrutinasinternas.
Ejemplo:
#!/usr/bin/perl
$value = "GLOBAL";
simple();
doble();
simple();
sub doble {
local $value = "LOCAL";

simple();

#
#
#
#
#

creamos una variable semilocal


que puede ser usada dentro de otra
subrutina como si fuera global
solamente dentro de la subrutina
externa

# se imprime el valor local

sub simple {
}

# se imprime el valor global


print "El valor actual de \$value es $value\n";

exit;

Pag.111

HugoMazaM.Perlbsicodesdecero

Corremoselscriptydebeimprimirenpantalla:
user@host:~$ test.pl
El valor actual de $value es GLOBAL
El valor actual de $value es LOCAL
El valor actual de $value es GLOBAL
user@host:~$

7.7.1Reutilizacindecdigo
Deestaformapodemoscrearfuncionespropias,llamadascomnmentesubrutinas,las
cualespodremosreusarendistintasetapasdeunscriptdePerl.
Estosellamareutilizacindecdigoyseusanormalmenteparaahorrarprecisamente
cdigo,tiempoycargaenelservidor,quealfinaldeldasetraducecomoahorroen
efectivo.
Enmuchasocasionespodremosreusarestassubrutinasparadiferentesscriptsqueno
seanparaloscualesfueronescritos,yestolopodemoshacerfcilmentegenerandoun
archivodesubrutinasy"llamando"estearchivodesdeelscriptdePerlactualparaintegrarlo
comosifuerapartedel.
Loanteriorselogramedianteelusodelafuncinrequire:
Sintaxis:
require "path/to/file";

requireinsertaelcdigodentrodelarchivo,enelespaciocorrectodentrodelscriptdePerl.
Porejemplo,sihacemosunasubrutinaylacolocamosenelarchivosubs.pl(usamoseste
nombreparaidentificarladelscriptejecutable,ustedpuedeponerleelnombrequedesee).
YposteriormentecreamoselscriptdePerl,quellamealarchivoconla(s)subrutina(s).
Ejemplo:
Vamosacrearunmecanismoparagenerarpasswordaleatorio.
Archivosubs.pl:
Pag.112

Conejemplossencillosparaautomatizacindetareasenservidores
##### archivo subs.pl que guarda subrutinas para diferentes usos
sub genera_passwd {
my $max = shift;
my @chars = (A..Z, a..z, 0..9);
my $contra;

# generamos rangos de caracteres


# de letras y nmeros que
# puedan usarse en un password

for ( 1 .. $max ) {
$contra .= $chars[rand @chars];
# usando la funcin rand
# seleccionamos aleatoriamente
# un elemento del array
}
}
1;

return $contra;
# al retornar al script debe ser con valor verdadero

Loquehacemosaquesseleccionarunndicedelarray@arrayparaconcatenarloamas
elementosseleccionadosyobtenerunamezcladecaracteresaleatoriosqueformenun
password.
Doscosasqueaprendermas.
a)AquusamosunafuncinmasdePerl,rand,lacualgeneraenformaaleatoriaun
nmerodelosquelepasemoscomoargumento.
b)Alfinaldelarchivoqueinsertamosconrequire,colocamosunalnea:1;,lacualnos
aseguraquelainsercinmedianterequiresetermincorrectamenteyentoncesregresaun
valordeverdadero,locualnospermitecontinuarconelscriptenformacorrecta.
Noteadems,quenoesunscriptdePerlpropiamentedicho,yaquenoseejecuta.Y
debidoaesto,desdeluego,noesnecesarioquetengapermisosdeejecucin.
AhoraelscriptdePerl:

Pag.113

HugoMazaM.Perlbsicodesdecero
#!/usr/bin/perl
my $maxChar = 6;

# configuramos el largo del password

require "subs.pl";

# llamamos e insertamos el cdigo dentro del


# archivo subs.pl en esta parte del script

my $passwd = genera_passwd($maxChar);

print "Tu password es: $passwd \n";

#
#
#
#

corremos la subrutina que


fsicamente se encuentra en el
archivo subs.pl, pero que ahora
forma parte del script

exit;

Ejecutamoselscript:
user@host:~$ test.pl
Tu password es: 1EwSS1
user@host:~$
user@host:~$ test.pl
Tu password es: KdFLT6
user@host:~$
user@host:~$ test.pl
Tu password es: DiLOl3
user@host:~$
user@host:~$ test.pl
Tu password es: 7Q5ub0
user@host:~$

Cadavezqueejecutamoselscript,nosimprimeunacadenadiferente.
Aestasalturastodoloquehacemosenestescriptdebesercomprendido...oesoespero.

Pag.114

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO8

Entrada/SalidaenPerl.Archivos
Pag.115

HugoMazaM.Perlbsicodesdecero

Pag.116

Conejemplossencillosparaautomatizacindetareasenservidores

8.Entrada/SalidaenPerl.Archivos
PerlinteractaconelusuariooconelsistemaoperativopormediodeEntradas/Salidas
(Input/OutputosimplementeI/O)quepermitenelintercambiodeinformacin.
Esteintercambiodedatossegestionapormediodemanejadores(handle)especficosque
mantienenabiertaunainterfazentreelscriptysuentorno.
8.1Manejadoresdeentrada/salidadedatos(I/OFilehandle).
UnFilehandleenPerl,eselnombredeunaconexinentreelprocesodePerlyelmundo
exterior.
Deformaimplcita(comolavariable@_queestudiamosanteriormente)Perlcreaalgunos
manejadoresdeI/Oquenonecesitamosdeclararcuandolosusamos.
Deestosmanejadoresyahemosusadoalgunossindarnoscuentaalolargodelestudiode
estelibro:
STDOUT

(StandardOutput)Lasalidaestandardobien,nuestraterminalomonitor.

STDIN

(StandardInput)Laentradaestandardobien,elteclado.

STDERR

(StandardErroroutput)Eslasalidadeerroresdelsistema.

8.2Laentradaylasalidaestandard
Podemosverahoraquealusarlafuncinprint,sololehemosdichoquimprimiryPerl
interpretahaciaquemanejadorvaadirigirlasalida,yahoranosdamoscuentaqueesla
STDOUT.
print "Algo que imprimir\n";

Eslomismoque:
print STDOUT "Algo que imprimir\n";

AunquenonecesitamosdeclararquevamosadirigirlasalidaalaStandardOutput.
Pag.117

HugoMazaM.Perlbsicodesdecero

Perlaceptaunanomenclaturasinunprefijoespecial(comoenlasetiquetas)paralos
manejadoresI/O.
SerecomiendausarsiempreunanomenclaturaconMAYSCULASparaevitarconfusiones
duranteeldesarrollodelscript.
Perltambinnospuedepermitirusarunavariableescalarcomomanejador,porejemplo
$miarchivoparadeclararunmanejador,elcualdebeestardedicadosoloparaesteuso.
As,podemosusarmiarchivo,oMIARCHIVO,obien,$miarchivo,delosqueserecomienda,
comoyasedijo,MIARCHIVO,enmaysculas.

Ahora,podemostambinadministrarlaentradaestandardSTDIN:
#!/usr/bin/perl
print "Cual es tu nombre? ";
$name = (<STDIN>);

# El script espera a que ingreses una cadena y enter


# si no, no puede continuar

chomp $name;

# quitamos el salto de lnea, si lo hay

print STDOUT "Bienvenido $name\n";

# STDOUT sale sobrando

exit;

8.3AbrirycerrararchivosenPerl
ExisteunafuncindePerlparadeclararfilehandlesadicionales,eslafuncinopen,lacual
tienelasiguientesintaxisparalaaperturadearchivos.
Sintaxisparaabrirunarchivo:
open (MANEJADOR, "modo_de_acceso + nombre/de/archivo")

Sintaxisparacerrarelmismoarchivo:
close (MANEJADOR);

Elnombredelarchivoincluyesurutadeacceso.
Pag.118

Conejemplossencillosparaautomatizacindetareasenservidores

Losmodosdeaccesomasbsicosson:
>
>>
<

Escritura. Vaca el archivo antes de escribir. Ojo con este.


Escritura. Escribe al final del archivo, concatenando el contenido.
Lectura.
Si no se establece modo_de_acceso, este es por defecto,
y abre un archivo para su lectura.

8.4Elaccesoaarchivos
Unavezqueabrimosunarchivoparalectura,lopodremosaccesarpormediodelos
operadoresdedatos<y>,loscuales"leen"elarchivolneaporlnea.
Ejemplo:
Supongamosquequeremosleerlaslneasdelarchivo/etc/passwddenuestrosistema
operativoUnixoGNU/Linux.
open (CONTRAS, "/etc/passwd");

# abrimos el archivo para lectura


# tambin podemos usar "</etc/passwd"

while (<CONTRAS>) {

# leemos lnea por lnea

chomp;
print "$_ \n";
}
close CONTRAS;

# quitamos los saltos de lnea de $_


# imprimimos la lnea en turno

Tambinpodemoscargartodoelcontenidodelarchivoenunarray.EnestecasoPerl
identificaquecadasaltodelnearepresentaellmitedeloselementos,poniendocadalnea
comounelementodelarray:
open (IN, "</etc/passwd");

# abrimos el archivo para lectura

my @lineas = <IN>;

# cargamos todo el archivo en un array

close IN;

Esteltimomtodotieneladesventajadequesielarchivoesmuygrande,lamemoriade
nuestroequiposevedisminuida,porquecargamostodaslaslneasdelarchivoenunasola
variable.
Igualmente,podemosimprimirenunarchivo,segnelmododeapertura:
Pag.119

HugoMazaM.Perlbsicodesdecero
open (OUT, ">/tmp/file.txt");

# abrimos el archivo para escritura


# vacindolo antes

print OUT "Esta es una lnea de prueba\n";


close OUT;

# cerramos el manejador

# se imprime en el archivo
# debido al manejador declarado

8.5ManejodeerroresparaI/Odearchivos
Alcomanzaratrabajarconarchivos,enmuchasocasionestendremosproblemasparaabrir
archivospordistintasrazones.
Elcasoahoraesaprenderamanejaresoserroresanuestraconveniencia.
8.5.1Algunosmtodossimples
Sirecordamoslafuncinunless,nosejecutaunbloquecuandolaexpresinevaluadanos
devuelvefalso:
my $datafile = "/tmp/file.txt";
unless ( open (DATA, ">$datafile") ) {
print "No se puede crear $datafile\n";
} else {
my @arr = <DATA>;

# etc, etc...
# ... y el resto del programa se ejecuta completo cuando
# la expresin es verdadera, o sea, si se abre bien el archivo.

Claramentevemosquesinosepuedeabrirelarchivo,noseejecutaelrestodelprograma,
elcualterminasinhacernada.
8.5.2Lasalidadie
Otromtodounpocomasfcil,eliminandoelcomplementodeunless,else,esusarla
funcindie,lacualterminaunscriptcuandolausamos:
my $datafile = "/tmp/file.txt";
unless ( open (DATA,">$datafile") ) {

Pag.120

Conejemplossencillosparaautomatizacindetareasenservidores
die "No se puede crear $datafile\n";
}
my @arr = <DATA>;
# etc, etc...
# ... y el resto del programa se ejecuta completo cuando
# la expresin es verdadera, o sea, si se abre bien el archivo.

Aquvemosquenonecesitamoselseparacorrerelrestodelprogramacuandolaexpresin
evaluadaresultaverdadero,yaquesiresultafalso,simplementesalimosdelprograma.
Adicionalmentevemosquepodemosimprimiralgnmensajedeerrorcuandoestosucede.
8.5.3Eloperadororyeloperador||
Podemossimplificarmaslascosasusandoeloperadoror,encasodefallaalabrirun
archivo:
open (DATA,">$datafile") or die "No se puede crear $datafile\n";

Usualmentepodemostrabajarmasfcilmenteconeloperador||:
open (DATA,">$datafile") || die "No se puede abrir $datafile\n";

Tantoparalecturaoescritura,todofuncionaigual.
ExisteotravariableespecialenPerlquenosdevuelvelacadenadelmensajedeerror,yes
lavariable$!,lacualpodemosusaras:
open (DATA,">>/tmp/file.log") || die "Error: $!\n";

8.5.4Diferentessalidas
Puedenexistirocacionesenquenoqueramossalirdelscript,sinoadministrar
manualmenteloserrores.
Enestecasopodemosolvidarnosdelafuncindieyusarporejemplo,unadesviacin
haciaunasubrutina.
Regresemosalejemplodelasalarmasdesistemasdearchivosvistoenelpunto6.1.1.

Pag.121

HugoMazaM.Perlbsicodesdecero

Ahoraenlugardeimprimirlaalarmaenlapantalla,queremosimprimirlaenunarchivoque
enestecasoser/mnt/remoto/alm.txt,notandoquetalvezseaundirectoriomontado
remotamente,yesprobablequeenalgnmomentolaconexinnoestdisponible,porlo
quedeseamosguardarelerrorenotroarchivolocal...porsilasdudas.
#!/usr/bin/perl
$max = 70;
$sisdev = "/dev/sda3";
$almfile = "/mnt/remoto/alm.txt";
$logfile = "/tmp/test.log";
$comando = `df -k`;

#
#
#
#

umbral de alarma
sistema de archivos a monitorizar
archivo de alarmas
archivo log

# cargamos las lneas del comando a una variable

@lns = split(/\n/, $comando);


chomp @lns;
foreach $linea ( @lns ) {

# separamos cada lnea y las colocamos


# como elementos de un array
# por cada $linea del array @lns ...

if ( $linea =~ /$sisdev/ ) {

# si contiene el sistema
# de archivos deseado...

$linea =~ /.*\s([0-9]+)\%\s.*/;
$valor = $1;

# buscamos la columna y
# extraemos el valor

if ( $valor >= $max ) {

# comparamos el valor
# con el umbral

# (en una sola lnea)


$msg = "Alarma!: $sisdev en $valor\%. Igual o por
del umbral de $max\%";

encima

# aqu llamamos una subrutina si falla la funcin open


open (ALM, ">>$almfile") || sublog($almfile, $msg);
print ALM "$msg\n";
close ALM;

exit;
sub sublog {
my $file = shift;
my $msgAlm = shift;
my $msglog = "No se pudo abrir $file. Mensaje fallido: '$msgAlm'";

Pag.122

open (LOG, ">>$logfile") || die;


# ya no usamos otra opcin
print LOG "$msglog\n";
close LOG;
exit;
# ahora si, forzamos la salida

Conejemplossencillosparaautomatizacindetareasenservidores

Sirevisamosnuestrosistemadearchivosmonitorizado/dev/sda3ycolocamoselumbral
pordebajodeloquetengamos,elscriptdebebuscarlarutadelarchivo/mnt/remoto/alm.txt,
elcualcomoenrealidadnoexiste(nolohemoscreadoparalaprueba)nosdebellevarala
ejecucindelasubrutinasublog,lacualimprimeenelarchivo/tmp/test.log.
Alabrirelarchivo/tmp/test.logcontendrunasolalneaparecidaaesto:
No se pudo abrir /mnt/remoto/alm.txt. Mensaje fallido: 'Alarma!: /dev/sda3 en
74%. Igual o por encima del umbral de 70%'

8.6Laseguridadenelmanejodearchivos
Denadasirveaprenderelmejorlenguajedeprogramacinsinosetieneunaseguridadde
archivosenbuenestado,sincorrupcinoperdidos.
Lassiguienteslneasestndedicadasaello,ydebeustedponertodasufinaatencinen
estetema.
Lomasimportantealmanejardatos,sonprecisamenteunosdatoscompletos.
8.6.1FileTest,operadoresdecomprobacindearchivos
Quetalsiqueremosmanejarunarchivodenombresalida.logparaadministraralgunas
salidadeerroresdeunscript,pero(siemprehayunpero)nosabemossialgunavezya
creamosesearchivoconotroscriptyentoncesmezclaremoslosdatosyaexistentesconlos
nuevosgenerandounarchivoconlneasdediferentesformatosparaanalizar.
Entoncesgeneraremosuncaos.
Paraevitaresto,podemosusarlosfiletestdePerlquenosdaninformacinacercadel
archivoqueestamosmanejando.
Ejemplousandoe(devuelveverdaderosiexiste):
$archivo = "salida.log";
if (-e $archivo) {
print "Hey! el archivo $archivo ya existe! busca otro nombre\n";
} else {
print "El archivo no existe y se va a crear...\n";
# y sigue el programa
}

Pag.123

HugoMazaM.Perlbsicodesdecero

Sielarchivoexiste,laexpresinconeretornaverdadero,encasocontrariodevuelvefalso.
Haymuchosfiletests,ypodemosveralgunosacontinuacin:
-r

Archivo o directorio es de lectura

-w

Archivo o directorio es de escritura

-x

Archivo o directorio es ejecutable

-o

Archivo o directorio es propio del usuario

-R

Archivo o directorio es de lectura para el usuario real

-W

Archivo o directorio es de escritura para el usuario real

-X

Archivo o directorio es ejecutable para el usuario real

-O

Archivo o directorio es propio del usuario real

-e

Archivo o directorio existe

-z

Archivo existe y tiene tamao cero o vaco.

-s
Archivo o directorio existe y tiene tamao diferente de cero
(el valor retornado es el tamao en bytes)

Pag.124

-f

Es un archivo plano

-d

Es un directorio

-l

Es un symlink

-S

Es un socket

-p

Es un pipe declarado (un "fifo")

-b

Es un archivo block-special (como un disco montado)

-c

Es un archivo character-special (como un I/O device)

-u

Archivo o directorio es setuid

-g

Archivo o directorio es setgid

-T

Archivo es de tipo "text"

-B

Archivo es de tipo "binary"

-M

ltima modificacin en das

-A

ltimo acceso en das

-C

ltima modificacin del inodo en das

Conejemplossencillosparaautomatizacindetareasenservidores

Elfiletestsdevuelveeltamaoenbytesdelarchivoysuusopuedeser:
my $filesize = -s "/var/log/esearchivo.log";
print "El tamao del archivo es $filesize bytes\n";

8.6.2Bloqueodearchivos
Enmuchasocasionesesposiblequeunmismoarchivoestsiendousadopormasdeun
procesooscriptdePerl,yesfcilllegaratenererroresenesosarchivos.
Paraevitarestascatstrofesyllenarnosdearchivosinutilizablesyperdernuestrotrabajo,
esmuyaconsejabletenersiempremecanismosdeseguridadcuandoabrimosunarchivo,
evitandoqueotrospuedanhacerusodelmismo,sinuestroscriptyaloabriprimero.
Seusademaneramuycomnelbloqueodelosarchivos,tantoparaescrituracomopara
lectura.
Deestaforma,solounprocesopuedehacerusodelmismoauntiempo.
HaremosunparntesisparaexplicarbrevementealgomuyimportanteenPerl,yque
debemossaberparalassiguienteslneas.
Perlposeeunafuncindenombreflock()lacualhaceunllamadoalafuncinflockdel
sistemaoperativo,obien,unaemulacindeesta.
Sintaxisdeflock():
flock(FILEHANDLE, MODO);

DondeFILEHANDLEeselidentificadordelarchivoparaabrir,yMODOeslaformaenque
seestabriendo.
Losmodosmascomunesqueusamosson,sololectura(1)ycompleto(2).
Ejemplos:
open (FILE, "<mensajes.txt");
flock (FILE, 1);
my @mensajes = <FILE>;
close FILE;

# abrimos para lectura


# bloqueamos el archivo para que solo puedan
# leerlo cuando nosotros lo usamos

Pag.125

HugoMazaM.Perlbsicodesdecero

Deestaforma,nuestroscriptloabre,lobloqueaylolee,dejandoqueotrosprocesossolo
puedenleerelcontenido,nomodificarlo.
open (FILE, ">>mensajes.txt");

# abrimos para escritura

flock (FILE, 2);

# bloqueamos el archivo por completo para que


# no pueda ser accesado mientras lo usamos
print FILE "Esta es una linea insertada\n";
close FILE;

Cabemencionarquelafuncinflocktrabajacorrectamenteencasitodoslossistemas
operativos,exceptolosquenoposeenestafuncinanivelOS,porejemplo,MSWindows.
Ademsdelafuncinflock(),existendiversosmdulosparaprotegerelusodearchivos,
veremosunoqueotro,nosinantesplaticarsobrelosmencionadosmdulos.
8.6.2.1Muybreveintroduccinalusodemdulos
Sianteshablamosdesubrutinasquepuedenestarenotrosarchivosnoejecutables,los
cualespodanserllamadosmediantelafuncinrequire,ahorapodemoshacerusodeotro
tipodearchivosquetambinllevanvariasfuncionesdentro,aunquesuconstruccines
especialmentediferentedeunarchivodesubrutinascomn.
SonlosmdulosdePerl.
Estosdebenllevar,comosemencion,unaconstruccinespecialdelquenoeselcaso
hablardeello,sinembargosdebemoshablardecmosellamanlosmdulosdesdeun
script.
UnmduloenPerlsiempredebeterminaren.pm,locualloidentificacomomdulodePerl.
Aunquelleveunaconstruccindiferente,esungrupodesubrutinas,yesposiblellamarlo
conlafuncinnormalrequire.
Ejemplo:
require "modulos/modulo.pm";

Ypodremosusartodaslasfuncionesdentrodeste.(Notequeesunmdulodentrodeun
directorio)
Pag.126

Conejemplossencillosparaautomatizacindetareasenservidores

Elmtodomasexactoparallamarunmduloesmediantelafuncinuse.
Ejemplo:
use modulos::modulo;

Notequenolecolocamoslaterminacin.pm.
Noteadems,quemodulosesunsubdirectorioquecontieneelarchivomodulos.pm,yeste
seseparamedianteundoblecaracter:(::)
Conestemtodoadems,podemosimportarlasconstantesespecficasparanuestrouso
enelscript,yparanocargartodaslasfunciones.
Perl,ensusdistribucionesestandard,vieneconunabuenacantidaddemdulosquefueron
escritosporpersonasquelesinteresaquetodoslospodamosusar,yquenosresuelven
muchosproblemas.
Podemosas,reutilizarcdigodeotrosprogramadores.
8.6.2.2UsodeflockdelmduloFcntl
Lafuncinflock()queemulaelflockdelSistemaOperativotienealgunosproblemasde
usoespecialmenteconalgunossistemasoperativos.
Paraevitaresto,podemostrabajarconbloqueosmedianteelmdulogenricofcntl,del
cualpodemosimportarlasconstantesLOCK_*.
Peroveamosunejemplo:
#!/usr/bin/perl
use Fcntl ':flock';

# importamos el mtodo flock que incluyen


# las constantes LOCK_* del mdulo Fcntl

open (FILE, "</path/mensajes.txt");


flock(FILE, LOCK_SH);

# LOCK_SH... de shared

my @mensajes = <FILE>;
close FILE;

Pag.127

HugoMazaM.Perlbsicodesdecero

AqubloqueamoselarchivoparalecturaconLOCK_SHyquedacompartidoparaque
puedaserledoporotrosprocesos.
Yenesteejemplo:
#!/usr/bin/perl
use Fcntl ':flock';

# importamos el mtodo flock


# y las constantes LOCK_* del mdulo Fcntl

open (FILE, ">>/path/to/file");


flock(FILE, LOCK_EX);

# LOCK_EX... de exclusive

print FILE "Este es un mensaje en una linea\n";


close FILE;

BloqueamoselarchivoenformatotalconLOCK_EX,paraquenopuedaseraccesadoni
paralecturaymenosparaescritura.
Estemtodoeslimpioynodejarastrosdeuso,comolafuncinsimpleflock().

8.6.3MtodoMazadeseguridad(delautor)
Quetalsiqueremosabrirunarchivoparaescribirloynuestroscriptsedacuentadequeno
lopuedeabrir,debidoaqueotroscriptloestusando,enesecasoydeacuerdoaunscript
anterior,delaseccin8.5.4,nosescribirenunarchivologunalneaquenosindicaqueno
pudoabrirelarchivoparaescribirlo.
Sinoqueremosqueesopaseydeseamosqueintenteenformarepetidaelabrirelarchivo
hastaqueloconsiga(cuandoelotroprocesolodesbloquee),entoncespodemoshaceruso
denuestrapequeaexperienciayusaralgnmtododereintento.
Suservidor,elautordeestelibro,oseayo,hiceunapequearutinaparaesperaraque
otroproceso"suelte"elarchivoyeneseentonces,tomarloparatrabajarenl.
Esmuysimple,perofunciona.
CdigodelmtodoMazadeseguridadparaarchivos:
Pag.128

Conejemplossencillosparaautomatizacindetareasenservidores
while (1) {

# generamos un bucle infinito

flock(FILE, LOCK_EX) or next;


last;

# si no se puede bloquear, sigue con


# el ciclo ...y vuelve a intentarlo

# cuando llegue a este punto es porque s se pudo bloquear


# y entonces sale del bucle while para no intentar de nuevo

}
# ...y continuamos con el script

Deestaformanosaseguramosdeque:
Elarchivoausardebaestarlibreparasuuso
Elarchivolobloqueamoscuandodejedeestarocupado
Elscriptnoprosiguehastaquesepuedabloquearelarchivo.Tampocotermina.
Adicionalmentepodemosponerleuntopealbucleyesperarsolonintentosdebloqueo,en
lugardehacerloinfinito.
Otalvezpodamostemporizarloparaesperarunosminutosydespus,sinoconseguimos
bloquearloprocederaguardarelerrorenelarchivolog.
Sireducimoselmtodoasumnimaexpresin:
# metodo Maza de seguridad
while (1) { flock(FILE, LOCK_SH) or next; last; }

Ahorahagamoselmismoscript,conreintentosyconproteccindeintentos:
$cnt = 0;
while (1) {
$cnt ++;

# inicializamos el contador de proteccin


# generamos un bucle infinito
# incrementamos en 1 cada vez

# si llega al lmite $maxEspera, a hora si, la subrutina


sublog( "/path/to/file", $msg ) if $cnt eq $maxEspera;

flock(FILE, LOCK_SH) or next;


last;

print FILE "$msg\n";


close FILE;

Ysiqueremosasegurarnosdequeseabra,ademsdequesebloqueecorrectamente?
Elejemplocompletoquedaraas:
Pag.129

HugoMazaM.Perlbsicodesdecero
#!/usr/bin/perl
use Fcntl ':flock';
$logfile = "/tmp/test.log";
# archivo log
$maxEspera = 100000;
# mximo nmero de intentos
$msg = "Este es un mensaje en una linea";
# mtodo Maza de seguridad, aplicado a la funcin open
$cnt = 0;
while (1) {
$cnt ++;
sublog( $logfile, "Fallo en apertura" ) if $cnt eq $maxEspera;

open(FILE, ">>/path/to/file") or next;


last;

# mtodo Maza de seguridad, aplicado al bloqueo de archivos


$cnt1 = 0;
while (1) {
$cnt1 ++;
sublog( $logfile, "Fallo en bloqueo" ) if $cnt1 eq $maxEspera;

flock(FILE, LOCK_SH) or next;


last;

print FILE "$msg\n";


close FILE;
exit;
sub sublog {
my $file = shift;
my $msgAlm = shift;
my $msglog = "No se pudo abrir $file. Mensaje de falla: '$msgAlm'";

open (LOG, ">>$logfile") || die;


# ya no usamos otra opcin
print LOG "$msglog\n";
close LOG;
exit(1);
# y ahora si, forzamos la salida (sin error)

Deestemodo,sinoconseguimosabrirunarchivodespusdeunnmerodeintentos
determinado,generamosunalneaenelarchivolog.
Delmismomodo,sinopodemosbloquearunarchivodespusdeundeterminadonmero
deintentos,tambingeneramosunalneaenelarchivolog,coneldebidomensajedeerror.
Conestopodemosyacomenzaratrabajarenformaseguraconarchivos.
Pag.130

Conejemplossencillosparaautomatizacindetareasenservidores

Quedapendienteelusodelmtodocontemporizadorenlugardecontadordeintentos.
Siaustedseleocurreotromtodosimpleyfcilparaasegurarelmanejodelosdatosen
archivos,nodudeencompartirloconelrestodelmundo,hayqueregresarunpocodelo
muchoquestenoshadado.
Talvezquieraenviarloamicorreoyenlaprximaedicinlopublicamosconsudebido
mensajedeautora.
8.7Manipulacindearchivosydirectorios
PerlposeefuncionesparecidasalasfuncionesdelosSistemasOperativosUnixo
GNU/Linux,loscualestienenusossimilares.
Ademsdelamanipulacindearchivos,incluimostambinladedirectorios,puesesalgo
quesiempredebemoshacerennuestrocaminarporelmundodeServidores.
8.7.1Removiendounarchivo
Lafuncinunlink()borraunarchivo.
Sintaxis:
unlink ("file");

Comoejemplo,hagamosuncomandoparaborrarunarchivo:
#!/usr/bin/perl
$aborrar = shift;

# captamos el argumento $_[0]

unlink $aborrar;

# borramos el archivo dado por el argumento

exit;

Siloejecutamos:
hmaza@hmaza:~$ del.pl /tmp/test.log
hmaza@hmaza:~$

Estonosborraelarchivoqueestbamosusandocomosalidadelogdeerroresquele
pasamoscomoargumentoyclaro,nosdejasinpoderanalizarlos.
Pag.131

HugoMazaM.Perlbsicodesdecero

8.7.2Renombrandounarchivo
Pararenombrarunarchivousamoslafuncinrename().
Sintaxisconejemplo:
rename("nombre_antiguo.pl", "nombre_nuevo.pl");

8.7.3Creandoyremoviendodirectorios
Lasfuncionesmkdir()yrmdir()soncapacesdecrearyremoverdirectorios,claro,vacos.
Sintaxisconejemplo:
mkdir("directorio", 0777) ;

Creaundirectorioconlospermisosquesedesee.
rmdir("directorio");

Remueveundirectoriosisteestvaco.
8.7.4Permisos
EnformasimilaralcomandochmoddeUnix,tenemoslafuncinchmod()dePerl.
Sintaxisconejemplo:
chmod(0666, "archivo");

obien,modificandovariosarchivosalavez:
chmod(0666, "file", "archivo", "otro_archivo");

8.8Otrosmodosdeacceso
Ademsdelosmodosdeaccesoaarchivosqueyavimos,comoel>>o<,podemos
accederaunarchivonoparaabrirloalecturaoescritura,sinoparaejecutarloypasarle
Pag.132

Conejemplossencillosparaautomatizacindetareasenservidores

argumentos,recibirdatos,etc.
8.8.1LoscanalesPIPEsdecomunicacin:
Paraestousamosenlugardelosmodosdeaccesodelecturaoescritura,elpipe(|)para
informarlealafuncinopen()quequeremosestableceruncanaldecomunicacinconun
archivoejecutable.
Parailustrarelusodelpipe,generaremosunscriptqueenveuncorreoelectrnico
medianteelcomandodeUnixsendmail,elcualdebemossaber,lasintaxisbsicaes:
user@host:~$ sendmail -t...

Veamoselejemplo:
#usr/bin/perl
my
my
my
my

$sendmail = "/usr/sbin/sendmail -t";


$from = "sender\@dominio.com"; # no olvidemos el backslash
$to = 'destinatario@dominio.com'; # recordemos las comillas simples
$subject = "Mensaje de prueba";

open(MAIL, "|$sendmail");
print
print
print
print
print

MAIL
MAIL
MAIL
MAIL
MAIL

# abrimos el comando para ejecutarlo

"From: $from\n";
# el From: de sendmail
"To: $to\n";
# el To: de sendmail
"Subject: $subject\n\n";
# Subject:, de sendmail
"Este es un mensaje de prueba, para ver si funciona\n\n";
"Si lo recibe, favor de no hacer caso\n";

close MAIL;
exit;

# cerramos el canal de comunicacin

Obviamente,elprogramasendmaildebeestarinstaladoenelservidorparapoderusarlo
conPerl.
Enesteejemplovemosquelafuncinopen(),abreuncanaldecomunicacincon
sendmail,yposteriormenteimprimimosvarioscomandoscomoelconocidoFrom:,yotros
mashastacerrarloyenviardeestemodo,elcorreoelectrnico.
Estolopodemosusarparanotificarlasalarmasdelosservidorescuandohayproblemas.
Loveremosenlassiguientespginas.
Pag.133

HugoMazaM.Perlbsicodesdecero

Pag.134

Conejemplossencillosparaautomatizacindetareasenservidores

CAPTULO9

Desarrollodescripts
Pag.135

HugoMazaM.Perlbsicodesdecero

Pag.136

Conejemplossencillosparaautomatizacindetareasenservidores

9.Desarrollodescripts
AhorapodemoscomenzaradesarrollarprogramasquehacenalgopornuestrosServidores
olosprocesosquemantienentrabajando.
Eselcasomencionarquepodemosusaromejordicho,reusarcdigoqueyahasido
escritoycomprobadoquefuncionaadecuadamente.
YaaprendimosligeramenteausarlosmdulosdePerl,queenlarealidadpuedenser
Paquetes.
Aunquepuedenserlomismo,haydiferenciasentreambos.
UnPaqueteenPerl,tieneprovistounaproteccinespacialdentrodelscript,esunaseccin
decdigoquepuedeono,interactuarconelrestodelscriptoconotrosPaquetes.
Unpaquetepuedeestarcolocadodentrodeunscript,delimitadosoloporelusodela
declaratoriadePaquete:
package NombrePaquete;
# resto del paquete

UnMduloesunPaquetereusablequehasidodefinidocomolibreraparasuuso.
Unmduloespues,unarchivoounalibreraquecontieneunPaqueteocoleccindeellos.
ElarchivodelMdulodebeterminarforzosameneen.pm(yalohabamosvisto).
Yaaprendimosquellamamosaunmdulodentrodeunscriptporlafuncinuse,
prefirindolasobreelusoderequireporraznesdeseguridadeimportacindeconstantes
yfunciones.
Ahoraveremosalgunosmdulosylaformaenquenospuedenayudaracrearscriptsde
usoenlaempresacongrandesomuygrandes(oinclusoconpequeas)capacidadesde
manejodatos.
RepetimosquenoeslaintencindeestelibroprofundizarconMdulosyPaquetesnisu
construccin,porloquesolonoslimitaremosasuexplotacinparanuestrospropsitos.

Pag.137

HugoMazaM.Perlbsicodesdecero

9.1Elpragmastrict
Lospragmas(quesonmuchos.Ver:http://perldoc.perl.org/indexpragmas.html)son
directivasdelcompiladoryconestoleindicamoscomodebeactuarconnuestrosscripts.
Strictesunpragmapararestringirlaseguridaddenuestrasconstrucciones.
Llamamosalpragmastrictcomosellamaunmdulocomn:
o
o
o

use strict;
use strict "vars";

# solo restringe variables

use strict "refs";

# solo restringe referencias simblicas

use strict "subs";

# solo restringe las subrutinas

Sinodeclaramosunalistaaimportar,seasumentodaslasrestriccionesposibles
Enlaprcticaesampliamenteusadalaformageneraldestrictporserlamassegura:
#!/usr/bin/perl
use strict;

Cuandousamoselpragmastricthabrquedeclararoinicializarcadaunadelasvariables
queusemos,ascomolasqueestndentrodelasfuncionesdePerlylaspropias,yasea
conmy,our,localocualquiermtododelmismoefecto.
Tambinhabrqueentrecomillarlasvariablescuandonosonsubrutinasoidentificadores
dearchivo.
Estonosayudaaformalizarcadaunadelasrutinas,bifurcaciones,buclesysalidasde
nuestroscript,haciendoestemasseguroycorrectoensufuncionamientoydesarrollo,y
eliminandolasfamosasinconsistenciasquenospuedendarmuchosdoloresdecabeza.
Enresumen,hayqueusarlosiempre.
9.2Objetosdelosmdulos
Queesunobjeto?
Muchadebeserlacuriosidaddellectorparasaberqueesunobjeto,comofuncionany
Pag.138

Conejemplossencillosparaautomatizacindetareasenservidores

comousarlo,puesseoyecontinuamentedeestosenmuchosscripts.
Ennuestraobrasolotrataremosloltimomencionado,cmousarlos,puesnoeslaobra
dedicadaaaprenderlaconstruccindeobjetosenPerl,cosaparalacualexisten
documentosespecializados.
Unobjetoesunavariable,siemprereferenciada,queenglobaensuinteriordatosy
cdigo,yquesabesiempreaqueclasepertenece.
Unaclaseessimplementeunpaquetequesabeexactamentequemtodos
proporcionarparatratarlosobjetos.
Unmtodoessimplementeunasubrutinaqueesperaunareferenciaobjetiva(oun
nombredepaquete,paramtodosdeclase)comosuprimerargumento.
Fcilno??
Parapoderhacerusodeunpaqueteomdulodebemosforzosamenteiralrepositoriode
stos,endondeencontraremoslosmtodos(osubrutinas)quepodamosusarycmo
debamosusarlos.
LaURLdelrepositoriomasgrandedePerl,elCPAN,es:
http://search.cpan.org/

Endondesetieneunbuscadorpormediodelcualpodremosencontrarmedianteuna
palabraclave,algoquenosayudeatrabajarconnuestroproyecto.
Casisiemprehayalgoquenosapoye.
Ydesdeluego,juntoconcadamduloparaPerl,habrsiempreexplicacionesyejemplos
parausodelosmtodosqueposeen.
9.3AlgunosEjemplosprcticos
Unodelosobjetivosdeestelibroesaprenderalgunascosasquenosayudenaautomatizar
tareas,oamonitorizarrecursosoprocesos.
Enestapartedelaobrapretendemoscolocarunapequeapartedenuestraexperienciaen
elambientedeServidoresenelrubroantesmencionado.
Pag.139

HugoMazaM.Perlbsicodesdecero

LossiguientesejerciciosayudarnallectoraobtenerunacercamientoalosscriptsdePerl
yaperderleelmiedoastos.
Pngasecmodoporquedaremosunpequeopaseoporelfabulosomundodelos
Servidoresindustriales.
Hayqueiniciarconalgosimple...
9.3.1Ejercicio1:
Extraerlafechadelsistemaparamanejarlaenunscript.
PrimerodebemossaberdelaexistenciadedosfuncionesmasdePerlquepuedenusarse
enunscriptdePerl:
time

Retornaelnmerodesegundosdesdeel1deEnerode1970

localtime

Convierteunacadenaensegundosyregresaunalistade9elementos:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)

Combinandoestasdosfuncionesnosretornadatosimportantesdelafechayhoralocal:
localtime(time);

Sabremoslossegundos,minutos,etc.yelaoenelqueestamosactualmenteconla
simpleorden:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

Obien:
my @fecha = localtime(time);

Conociendoelordendeloselementossabremoscualessoneimprimirlosdatos:
#!usr/bin/perl
@fecha = localtime(time);
foreach (@fecha) {
print $_, "\n";
}

Pag.140

Conejemplossencillosparaautomatizacindetareasenservidores

Queimprimirlosnueveelementosdevueltosporlocaltime.
Peroalaonoslomostrarcomo109(siestamosenel2009),perocomosabemosque
nosmuestralacantidaddeaostranscurridosdesde1900,asquedebemosagregarleal
elementoquerepresentaelao,el5elemento(comolapelcula),1900mas,as:
#!usr/bin/perl
@fecha = localtime(time);
$fecha[5] += 1900;

# es el elemento que representa el ao

foreach (@fecha) {
print $_, "\n";
}

Deestamanera,elsextoelementonosmostrar2009enlugarde109.
Recordemoslafuncinmap,lacualrecorreiterativamenteloselementosdeunarrayo
lista,ypuedecambiarlossilodeseamos.
Lasintaxis:
map { INSTRUCCIONES_POR_CADA_ELEMENTO } @array;

Elmismoscriptanteriorlopodemoshaceras:
#!/usr/bin/perl
@fecha = localtime(time);
$fecha[5] += 1900;
map { print $_, "\n" } @fecha;

Ahora,elmesobviamenteestarequivocado,yaquelafuncinlocaltimenosregresa
desdeelmescerohastael11(queson12mesesdelaoentotal),ydebemosagregarle1
alelementodelmes:
$fecha[4] ++;

Adems,comolossegundos,minutos,etc.quesenosdevuelveconlocaltimenotienenel
formatoquedeseamostener,porejemplo,02o05,debemosagregarleunceroalas
constantesquesonmenoresa10.
Paraestodebemos"transformar"elcontextonumricoacadenadetextodeeseelemento.
Pag.141

HugoMazaM.Perlbsicodesdecero

Conlafuncinmapharemosesto:
@fecha = map {
if ($_ < 10) {
$_ = "0$_";
} else {
$_;
}
} @fecha;

# Si es menor a 10
# agregamos un cero a la izquierda y
# lo manejamos como cadena de texto
# si no, lo dejamos as... Esto es relleno

Ahora,sideseamosqueestemtodoestdisponibleparaserreutilizadoporotras
subrutinasdurantetodoelscript,laconvertimosenfuncinpropia:
#!/usr/bin/perl
sub sysdate {
# nuestra funcin
@f = localtime(time);
$f[5] += 1900;
$f[4] ++;
# el mes 0 ser el mes 1 y as....
@f = map {
if ($_ < 10) {
$_ = "0$_";
}else{
$_;
}
} @f;
}

# Si es menor a 10
# agregamos un cero a la izquierda

return "$f[5]-$f[4]-$f[3] $f[2]:$f[1]:$f[0]";

Deestaformacuandohagamosusodenuestrafuncinsysdate,porejemplo:
print sysdate(), "\n";

estonosdevolverlafechaconformato:
2009-02-05 22:00:00
(En formato: Ao-Mes-Da Hora:Minutos:Segundos)

Comoelelementodelaonuncavaasermenorque10,nodebemospreocuparnosdel.
9.3.2Ejercicio2:
Monitorizareltamaodearchivoslogparaquenocrezcamasdeltamaopermitido.
Pag.142

Conejemplossencillosparaautomatizacindetareasenservidores

Planteamoslasituacin:
EnlossistemasOperativosdeServidor,quesonensuinmensamayoradetipoUnixo
GNU/Linux,tenemossiemprearchivoslogquesonarchivosderegistrodeactividades,
movimientos,alarmas,etc.
Comoenlamayoradelasveceslosmecanismosqueescribenenesosarchivosnose
preocupandeadministrareltamaodelosmismos,debemoshacerlonosotrosparaqueen
algnmomentodadonotengamosunosarchivosconeltamaodevariosGBqueal
momentodeanalizarlosesmuylento,asmismosurecorridoporlossistemasde
administracindealarmas.
Generaremosentoncesunasubrutinaquerevisesitieneeltamaomximoestablecido
(pornosotrosmismos)ysiesasenesemismomomentolecambieelnombreaotrocon
terminacindenmeroconsecutivoycreeunonuevo,escribiendoeneseltimo,quetiene
tamaocero.
Podramosprimerocopiarelarchivoaunoconterminacinconsecutivaydespusvaciarlo,
perosimidemuchosMBelprocesoeslentoydenadanossirvesiluegolovaciaremos.
Asqueseleccionamoselprimermtodo.
Paraqueestofuncionegildeberemoscontenerelltimoconsecutivoguardadoenun
archivodedicadoaeso,paranohacerunalistadelosarchivosyencontrarelltimo
consecutivo.
Ascadavezquenecesitemossabercualeselltimoconsecutivosololeeremosese
archivosysabremoscuales.
Comenzamoselejemplo:
my
my
my
my

$max_size = 10485760;
#10 MB
# el tamao mximo otorgado
$file_consecutivo = "./file.consec";
# el contenedor del consecutivo
$file_log = "./myfile.log";
# el archivo log principal
$mensaje = "Este es el mensaje a escribir en el archivo log";

if ( -s "$file_log" > $max_size ) {


# si pasa el umbral...
open (FILE, "<$file_consecutivo");
my ($consec) = <FILE>;
# sabemos cual es el ltimo
close FILE;
$consec += 1;
# aumentamos el consecutivo en 1
rename($file_log, "$file_log.$consec"); # movemos el archivo log
# hacia otro con terminacin consecutiva
open (FILE, ">$file_consecutivo");

Pag.143

HugoMazaM.Perlbsicodesdecero
print FILE "$consec";
close FILE;

# nuevo valor del ltimo consecutivo

open(NEWLOG, ">$file_log");
print NEWLOG $mensaje, "\n";
close NEWLOG;

# el archivo log vaco (nuevo)


# imprimimos el mensaje nuevo

Deestamaneratenemosunarchivo*.logyotrodetipo*.consecelcualcontieneunnmero
querepresentaelconsecutivodelosarchivosantiguosquesondeltamaode10MB,y
queguardamoscomorespaldo.
Ejemplo:
alarmas.log
alarmas.log.1
Losmecanismosdeanlisistendrnqueleertantoelactual*.logcomoelltimorespaldo
paraprocesarlainformacindebida.
Losdemspodrnborrarsecadaciertotiempo.
Estemateriallopodremoscolocarcomounafuncinpropiaalquelepodamos"pasar"
argumentosquesonlosnombresdelosarchivos,eltamaomximo,etc.
sub print_log {
my $max_size = shift;
my $file_consecutivo = shift;
my $file_log = shift;
my $mensaje = shift;
if ( -s "$file_log" >= $max_size ) {
open (FILE, "<$file_consecutivo");
my ($consec) = <FILE>;
close FILE;
$consec += 1;
# aumentamos el consecutivo en 1
rename($file_log, "$file_log.$consec"); # movemos el archivo log
# hacia otro con terminacin consecutiva
open (FILE, ">$file_consecutivo");
print FILE "$consec"; # nuevo valor del ltimo consecutivo
close FILE;

Pag.144

open(NEWLOG, ">$file_log");
print NEWLOG $mensaje, "\n";
close NEWLOG;

# el archivo log vaco (nuevo)


# imprimimos el mensaje nuevo

Conejemplossencillosparaautomatizacindetareasenservidores

Lasubrutinalatendramosquellamardeformaparecidaaesto:
print_log($max_size, $file_consecutivo, $file_log, $mensaje);

Declarandoanteslasvariablesenviadasalasub.
Otalvezalgomasprimitivo:
print_log(10485760, "./file.consec", "./myfile.log", "Mensaje X");

Claro,cadaquienleponelosnombresdearchivosylasterminacionesquenecesitapara
trabajar.
Aclaremosqueestoesunejemployquesepuedetomarcomobase,noesnecesariamente
queestodebaserasparacolocarloenproduccin,talvezsenecesitemoversolamentea
unarchivoderespaldoyunoriginalynocrearmasdeunacopia.Estemecanismolo
dejamosdetareaparaellector,ademsdelosmecanismosdeseguridaddearchivoscomo
losbloqueos.Porquelosarchivoslogtambindebenprotegerseconbloqueos.
9.3.3Ejercicio3:
Monitorizarelnmerodelneasdearchivoslogparaquenocrezcamasdelnmero
permitido.
Ahora,sinfijarnoseneltamaoenBytesdelarchivo,veremoscomopodemoslimitarel
nmerodelneasdeunarchivoparairborrandolasprimerasdelmismo,porqueyanonos
interesandebidoasuantigedad.
Comolasltimaslneassonlasmasnuevas,sonlasquenosinteresan.
Husmeandounpocoporelcpan(search.cpan.org),encontrunmduloexistenteenlas
distribucionesestandarddePerlquemepermitetrabajarconarchivoscomosifueraun
arrayycadalnea,unelemento,sunombre:Tie::File.
ConvieneallectoracercarseenestemomentoaladocumentacindeTie::Filepara
acostumbrarsepocoapocoaleerestadocumentacin.Yosemuybienquehastaeste
momentolamayoradeloslectores(yqueempiezanatrabajarconPerl)nolohahecho.
Veamoscomopodemostrabajarconestosdatos:
Primerodeclaramosnuestrasvariables:

Pag.145

HugoMazaM.Perlbsicodesdecero
my $max_lines = 5000; #
# mximo nmero de lneas
my $file_log = "./myfile.log";
# el archivo log principal
my $mensaje = "Este es el mensaje a escribir en el archivo log";

Yasabemosqueelnombredeunavariableescalarsolopuedecontenerletras,nmeroso
guinbajo,sinembargoexistenvariablesespecialesdentrodePerlcomoladelmensajede
errorqueyavimosenelpunto8.5.3,$!.
Tambintenemos$.,lacualnosindicaelnmerodelneaenlaqueestamosposicionados,
cuandounbuclerecorreiterativamenteunarchivoabierto.
Asqueestonosvaaservirparasaberelnmerodelneasquetenemosenunarchivo:
my $num_lines;
# nuestra variable global del nmero de lneas
open (FILE, "<$file_log");
while (<FILE>) {
$num_lines = $.; # cada vez que pasa una lnea, cambia de valor...
# en la ltima vuelta queda grabada en la variable
}
close (FILE);

Ahoraquetenemoselnmerodelneas,solonosquedacompararlaconeltamaomximo
delneaspermitidoyeliminarlassobrantes.
EselmomentodeutilizarelmduloTile::Filedelquehablamos,parahacerestoltimo.
my @contenido;

# declaramos la variable que ligaremos al archivo

my $oc = tie @contenido, 'Tie::File', "$file_log", memory => 0;


$oc->flock(LOCK_EX);

# bloqueamos el archivo con un mtodo establecido


# LOCK_EX de exclusive, no lectura, no escritura

if (@contenido) {

# nos aseguramos que el archivo no est vaco

if ( $num_lines > $max_lines ) { # si pasa el umbral...


my $dif = $num_lines - $max_lines;
for my $i ( 0 .. $dif ) {
$contenido[$i] = "";
}
}
} else {

Pag.146

# cuantas lneas de mas?

# por cada lnea de mas


# eliminamos esas lneas
# (vaciamos el elemento del array)

Conejemplossencillosparaautomatizacindetareasenservidores
}

print .= "Can't make TIE over \"$file_log\" \n";

$oc->flock(LOCK_UN);

# desbloqueamos el archivo

untie @contenido;

Lasegundalneanolacometamosporquevamosaanalizarlaunpoquitomasafondo.
Comocomentamosenlneasanteriores,Tie::File"enlaza"unarchivofsicamenteaunarray
denuestroscript.Ycadaelementodelarrayrepresentaunalneadelarchivo.
Inicialmentecreamosunobjeto($oc),resultadodehacerTiesobreelarchivo.Para
posteriormentebloquearloconlosmtodosquenosindicanenladocumentacinde
Tie::File.
Esasegundalneatieneunasintaxisclsicasegnladocumentacindelmdulo.
ElltimoelementodelalistadeconfiguracindeTie::Fileesmemory=>0.
Conestohacemosquelasmodificacionesserealicendirectamenteenelarchivo,ynoenel
bufferquemanejaTie.
Osea,quenoasignamosmemoriaalbufferdeTie::File.
RuegoallectornuevamentequeleabienladocumentacindeTie::Fileencpan.
Deestamanerasiempretendremosunarchivoconunacantidaddelneasrequerido...ni
unamas.
9.3.4Ejercicio4:
MonitorizacindeFilesystems.
Yasequehicimosunapequeaspruebassobreestetema,peropodemosampliarlaun
pocomas.
Loquenospedirnennuestrotrabajoprobablementeseralgocomoesto:
DebemostenermonitorizadolosFileSystemsdealgunosservidores,demaneraque,cada
filesystempuedatenerunumbraldiferente.
Ademsdeberemosgenerarunlogenalgnarchivo.
Finalmentedeberemospoderenviarunemailcuandolaalertasuceda.
Aparentementesevecomplicado,peronoloes,yaquehemosvistomuchascosasenel
transcursodenuestropequeolibro.

Pag.147

HugoMazaM.Perlbsicodesdecero

Comencemosporestablecerunarchivodeconfiguracin,alcuallepodremosagregarmas
lneascomovariablesdeseemostener,sinnecesidaddeabrirelarchivodelscriptpara
modificarlo.
#!/usr/bin/perl
use strict;
$configfile = "./fs.conf";

Comoqueremosqueelarchivotengaelformatoconvencionaldelamayoradelosarchivos
deconfiguracin:
# Comentario del archivo
VARIABLE = VALOR

Deberemossercapacesdeleeresearchivoytransformarsuslneasenvariableslegibles
paranuestroscript.
#!/usr/bin/perl
use strict;
use Fcntl ':flock';
my $configfile = "./fs.conf";
my %vars = ();
# declaramos nuestro hash para las variables
open(VARSENV, "<$configfile");
while (1) { flock(VARSENV, LOCK_SH) or next; last; }
# bloqueo maza
# para lectura
while (<VARSENV>) {
$_ =~ s/\s//g;
# quitamos los espacios
$_ =~ s/\n//g;
# es lo mismo que chomp

unless ( $_ eq "" || $_ =~ /^\#/ ) {


my ($llave, $valor) = split(/\=/, $_);
$vars{$llave} = $valor;
}

# si no es comentario

flock(VARSENV, LOCK_UN);
close VARSENV;

Dentrodelscriptcrearemosunhashparapodermeterahlasvariablesquequeramos.
Lobloqueamos.
Analizamoslneaporlnea.Lequitamoslosespaciosylossaltosdelnea.
Sinocontiene#alinicio,entoncesseparamosmedianteelsignode=,loqueeslallaveyel
valorparaluegocrearelelementodelhash.
Deestaforma,podremostenerencualquiermomentoelvalordecadavariableaccesible
parasuproceso.
Pag.148

Conejemplossencillosparaautomatizacindetareasenservidores

Porejemplo,declaramosenelarchivodeconfiguracinlavariable:
LOGFILE = alms.log

Cuandoqueramosllamaraestavariableparasabersuvalor,solotendremosquellamarla
llavedelhash%varsLOGFILEparasabersuvalor.
Comopruebayejemploimprimimoselvalordeesallave:
$vars{'LOGFILE'};

# imprime: alms.log

Nosimprime'alms.log',pueseselvalordeLALLAVE$vars{'LOGFILE'}.
Veamoscomopodemoscrearlo:
# Archivo de configuracin de file systems
# Formato: Variable = Valor
# Archivo para guardar las alarmas
ALMLOG = /path/to/alms.log
# Archivo para guardar los errores de ejecucin
ERRORLOG = /path/to/errores.log
# Crecimiento mximo de sistemas de archivos
# Para agregar mas sistemas de archivos a monitorizar
# solo agregue mas bloques en el formato:
# FILESYSTEMS = /path|umbral,/otro/path|umbral
# el umbral en %, ejemplo:
# FILESYSTEMS = /dev/sda1|80,/dev/sda3|50
FILESYSTEMS = /dev/sda1|80, /dev/sdb1|70
# recordemos que los espacios se eliminarn...
# Activar envo de email?
# 0 = no, 1 = s
ENVIO_EMAIL = 0
# cuentas de email para notificar las alarmas
# separadas por comas (,)
LS_EMAIL = hugo.maza@gmail.com.mx

Ennuestrocaso,decidimosseccionarelvalordelavariableFILESYSTEMSmedianteel
usodecomas,cadasistemadearchivoamonitorizarestseparadoporcomas',',ycada
seccindeestas,tambinlasepararemosporelpipe'|',aspodremossaberqu
porcentajemximodebemossoportarantesdeenviarunaalarma.
Pag.149

HugoMazaM.Perlbsicodesdecero

Yaseimaginarellectorqueusaremoslafuncinsplitvariasvecesduranteelscript.
Ybueno,veamoscomocontinuamosconeldesarrollo.
Primeovamosacrearunarrayconlossistemasdearchivoextradosenbruto,estoes,
contienentantoelfilesystemcomoelumbral:
my @fs = split (/\,/, $vars{'FILESYSTEMS'});

Ahoracrearemosunhashparatenercadafilesystemcomolallaveyelumbralcomoel
valor:
my %fshash;
foreach (@fs) {
my($lla, $val) = split (/\|/, $_);
}

$fshash{$lla} = $val;

# separamos por pipe


# ej: (/home, 80)

Despus(yestoyalovimos)ejecutaremoselcomandodfkdeUnixparaconocerlos
sistemasdearchivosysususos,ycolocamoslasalidaenunavariable,$cmd.
Estamismasalidalaseparamosenlneasylacolocamosenunarray:
my $almtxt;
my $cmd = `df -k`;

# cargamos las lneas del comando a una variable

my @lns = split(/\n/, $cmd);

# separamos cada lnea y las colocamos


# como elementos de un array

Ahoracomienzaloentretenido.
Porcadalneadelcomando,analizamossitieneunfilesystemasociadoysiesas,
usamosestacadenaparaformarlallavedelhash %fshash,locualnosindicaquesi
existeesallave,podremosprocederacompararelvalordelacargadelasalidadel
comando,conelvalordelelementodelhashparasabersiestdentrodelumbralono.
Veamos:
foreach my $linea ( @lns ) {

# por cada $linea del array @lns...

$linea =~ /^([0-9a-zA-Z\/]+).*/; # obtenemos el primer campo


my $sys = $1;
# que es la parte del file system
if ( $fshash{$sys} ) {

# si existe el sistema (la llave)...

$linea =~ /.*\s([0-9]+)\%\s.*/;
my $valor = $1;

Pag.150

# buscamos la columna y
# extraemos el valor

Conejemplossencillosparaautomatizacindetareasenservidores
if ( $valor >= $fshash{$sys} ) {

# comparamos el valor con el


# umbral
$almtxt .= "Alarma!: $sys en $valor\%. Igual o por
encima del umbral de $fshash{$sys}\% \n";

Siqueremosdemostrarquefuncionaantesdeproseguiragrabarlasalarmasenunlogy
sobretodo,aenviarcorreos,enestepuntodelscriptpodemosimprimirelresultado,
configurandolosumbralesmasabajodeloqueenlaactualidadestn.
Assabremosquefunciona:
print $almtxt;

Unavezqueprobamosquefunciona(ydebefuncionar),borramosesalneadeimpresiny
continuamosconelscript.
if ( $almtxt ) {
# si hay alarmas
my $fecha = sysdate();
# esta sub ya la establecimos antes
# imprimimos en el archivo log:
open(FILE, ">>$vars{"ALMLOG"}");
# bloqueo maza para escritura:
while (1) { flock(FILE, LOCK_EX) or next; last; }
print FILE "$fecha--$almtxt";
close FILE;

# imprimimos en sendmail para enviar correo si est habilitado:


# (si declaramos ENVIO_EMAIL = 0, no va a enviar correo)
if ( $vars{"ENVIO_EMAIL"} ) {
open(MAIL, "|/usr/sbin/sendmail -t");
print MAIL "From: root\@miserver.com\n";
print MAIL "To: $vars{'LS_EMAIL'}\n";
print MAIL "Subject: Alarma de File System sobre el umbral\n\n";
print MAIL "Con fecha $fecha, se cre alarma(s) de File System
sobre su umbral.\n";
print MAIL "$almtxt\n\n";
close MAIL;
}

exit;

Yas,nuestroscriptenvaalarmasvasendmailademsderegistrarlamismaenun
archivolog.

Pag.151

HugoMazaM.Perlbsicodesdecero

9.3.4.1Ejecucindelscriptvacrontab
Ahorasolonosfaltacolocarelscriptenelcrontabdelsistema.
Cada5minutosocadahora,dependiendodelaurgenciaconquedebaatendersela
alarma.
SielservidoresunequipoconGNU/Linux,esmuyprobablequesolosenecesitecolocarla
rutadelscriptenelcrontab.
PerosiesalgnsabordeUnixcomoSolaris,HPUX,etc.,comoestossistemasnocargan
lasvariablesdeambientedelusuarioqueejecutaelcrontab,esnecesariocargarestas
variablesdeambienteantesdeejecutarelscript.
Usualmentehacemosunejecutableenshellqueseejecuteencrontab,yestellamaal
scriptdePerldespusdecargarlasvariablesdeambiente,comoelHOMEyotros.
Ejemplodeentradaenelcrontabparalevantarelarchivoenshell:
#### MONITOREO DEL FILESYSTEM . CADA HORA
1 * * * * /root/scripts/FS/fs.sh >/dev/null 2>&1

Enelejemploanteriorseejecutacadahoraalminutouno,todoslosdas.
Claramentehacemosrecordarallector,queestelibroestdedicadoaaquellaspersonas
queadministransitesyquetienenmuypocaexperienciaonulaenprogramacin,peroque
ssabenmoverseenServidoresconSistemaOperativoPOSIXcompatible(Unix,Unix
Like).
Elscriptbash,dependiendodecualintrpreteusemos,puedeserdiferente...veamos.
EnShellBashsobreUbuntuServeroDebianconusuarioroot:
#!/bin/bash
. /root/.bashrc
export HOME=/root
# ESTO NO ES NECESARIO SI CORRE EN GNU/LINUX
/usr/bin/perl /root/scripts/FS/fs.pl

EnShellBashsobreRedHatoCentOSconusuarioroot:
#!/bin/bash
. /root/.bash_profile
#export HOME=/root
# NO LO USAMOS EN GNU/LINUX
/usr/bin/perl /root/scripts/FS/fs.pl

Pag.152

Conejemplossencillosparaautomatizacindetareasenservidores

EnKornShellsobreSolarisconusuarioroot:
#!/usr/bin/ksh
# Para Solaris
HOME=/root
. $HOME/.profile
/usr/local/bin/perl /root/scripts/FS/fs.pl

EnCShellsobreSolaris(Unix)conusuarioroot:
#!/usr/bin/csh
# Solaris
setenv HOME /root
source /root/.cshrc
/usr/local/bin/perl /root/scripts/FS/fs.pl

Estearchivofs.shdebetenerpermisosclaro,deejecucinparaquepuedafuncionar.
Adems,NOesrecomendablequeelscriptcorracomousuarioroot.

Otroaspectoquehayquetomarencuentaeslacantidaddecorreosquerecibiramossilas
alarmascomienzanelviernesporlatardeynosotrosnorevisamoselcorreohastaellunes
porlamaana.
Deberemosenesecasoposeermtodosdecontroldeenvodealarmas.
Siunamencionadaalarmayaseenvi,noenviarlasmas,obien,enviarlacontiemposmas
largosqueelnormaldelcrontab.
Peroestaesotrahistoria.
Ellectordebeponerafuncionarsusneuronasycrearporejemplounarchivoquelleve
controldelossistemasdearchivoalarmadosyenquehora,ysiyanohayalarmas,
eliminaresaentradadelarchivo.
Esfcil,solonecesitamosunpocodeprcticaendesarrolloconPerl...
Unaltimaaclaracinsobreesteejercicio,estaesunasolucinquesemeocurrimientras
escribaellibro,anteriormentehabaescritootrasolucinunpocodiferente,ytalvezla
prximavezsemeocurraotramuydistinta.
AltrabajarconPerl,cadaquehagamosalgo,podremoshacerlodistintoalaprimeravez,ya
queenPerl,comosulemaloindica,haymasdeunamaneradehacerlo.
Pag.153

HugoMazaM.Perlbsicodesdecero

9.3.5Ejercicio5:
PrcticasconelusodemdulosadicionalesdePerl
Ahoraquenoshemosadentradounpocoenelusodemdulos,vamosaejercitarnosun
pocoenelusodealgunos,unpocomascomplejosquelosqueyahemosvisto.
SeleccionunmduloquenovieneconladistribucinestandarddePerl,precisamente
parapoderhacerqueellectorpractiqueunpocolainstalacindeestos.
SetratadeunpaquetedePerlmuytilenunsinnmerodeocasiones,Net::SSH::Expect.
Unejemplodelautilidaddeestemdulo...laconectividadporSSHusandollavespblicas
(estoescomnentrelosadministradoresdeUnix)esfcilcuandosehaceentre
plataformassimilares,perosivamosaconectarporejemplo,unequipoconGNU/Linuxcon
otroconHPUXusandoSSHconllaveautomticadeautenticacin,esmuydifcilechara
andarestaconexin.
Esenestoscasosquenossirvemuchoestemdulo.
Lodescargamosdesearch.cpan.org.
Aldescomprimirloytratardeinstalarlousandolasfamosasinstrucciones,perlMakefile.PL,
make,maketestymakeinstall,nosdebearrojarunerrorenelqueapreciaramuchoque
tuvierasinstaladoelmduloExpect.
Peroesteasuvez,dependedeunaodoslibrerasmas,paraquedardebidamente
instalado.
SieststrabajandosobreUbuntuServer,estodeinstalarmdulosdePerlescasicomo
pedirlequeloinstaleporti,puestodaslasdependenciasseresuelven"automgicamente".
UnavezquetengamoslistoelmduloNet::SSH::Expect,vamosalimpiarnoslasmanosyel
sudordelafrente,despusdela"talacha"querealizamosenlainstalacinyprocedemosa
ejercitarnosenelusodeestemdulo.
EnladocumentacindelmduloNet::SSH::Expecthabladediferentesmtodosdeuso,
unodeellosesalmasbsico,eldecrearelnuevoobjetoparatrabajarsobrel,new,alque
iremosagregndolepropiedadesypodremosusarloendeterminadomomento,paracorrer
comandosenformaremota.

Pag.154

Conejemplossencillosparaautomatizacindetareasenservidores
my $scpe = Net::SCP::Expect->new;

Enlamismadocumentacin,vemosquepodemos"pasarle"argumentoscomomtodos.
Estos,comoveremosmuchasvecesenlosmdulos,puedenserenformadevariable
hash:(llave=>valor,llave=>valor):
my $host = '192.168.0.99';
my $user = 'usuario';
my $pass = 'pass101word';
# El mtodo new:
my $ssh = Net::SSH::Expect->new(
host
=>
$host,
user
=>
$user,
raw_pty
=>
1
);
# Y conectamos:
$ssh->run_ssh() or die "No puedo iniciar el proceso SSH: $!\n";

SieresusuarioavanzadodeUnix,habrsusadoalgunavezexpect,ycomoeste,tambin
elmdulodePerlNet::SSH::Expectesperaderegresoenlneadecomandos,algoconque
trabajar:
$ssh->waitfor('password:\s*\z');

# El servidor pide el password

Unavezqueelservidorharespondidopidiendoelpassword,selodamos:
$ssh->send($pass) or die "Password incorrecto\n";

Esenestemomentocuandoestamosyaconectados,ypodremosenviarconestemismo
mtodo"send"mascomandosyesperarrespuestaconelmtodo"waitfor".
Obien,ejecutarenformamasexactaloscomandosdeUnixycolocarlosenunavariable
parasuanlisisconelmtodoexec.
Vamosarealizarunpequeoscriptqueseconecteaunservidorlejano,seautentiquecon
supasswordcorrectoydespusverifiquesimplementequealgnarchivoexista.
Podremostambinhaceruntail(comandodeUnixqueleelasltimaslneasdeunarchivo)
paraobtenerloenunavariableyprocesarla.
Hagamoslaprcticacompleta:

Pag.155

HugoMazaM.Perlbsicodesdecero
#!/usr/bin/perl -w
use strict;
use Net::SSH::Expect;
my
my
my
my

$host
$user
$pass
$file

=
=
=
=

'192.168.0.99';
'usuario';
'password';
'/home/user/file.txt';

my $ssh = Net::SSH::Expect->new(
host
=>
user
=>
raw_pty
=>
);

$host,
$user,
1

$ssh->run_ssh() or die "No puedo iniciar el proceso SSH: $!\n";


$ssh->waitfor('password:\s*\z');
$ssh->send($pass) or die "Password incorrecto\n";
# Ejecutamos un comando simple de Unix para saber si existe un archivo:
my $stdout = $ssh->exec("ls $file");
# Si no regresa que no existe el archivo o directorio:
unless ( $stdout =~ /No such file or directory/ ) {
# Imprimimos el final del archivo:
my $tail = $ssh->exec("tail $file");
print "$tail\n";
} else {
print "El archivo no existe\n";
}
# Cerramos la conexin con el mtodo "close"
$ssh->close();
exit;

Yconestepequeoscriptvemosquepodemosconectarnosenformadesatendidadeun
usuario,revisarinformacinydepaso,administrarenformaautomtica,unServidor
remoto.
9.3.6Ejercicio6:
Ordenamientoporcamposdeunamatriz(AlgoritmodeMaza)
Dadaslasinnumerablesocasionesenquetengamoslanecesidaddeordenarlosdatosde
unarchivodetexto,haremosunejercicioparailustrarunaformagilderealizaresta
ordenacinnosoloporlnea,sinoporcampo,siacasohemoscolocadolainformacindel
Pag.156

Conejemplossencillosparaautomatizacindetareasenservidores

archivoenunamatrizdedatosdentrodeunavariableennuestroscriptdePerl.
Visualicemosunamatrizdedatos:
A0

A1

A2

A3

A4

A5

A6

B0

B1

B2

B3

B4

B5

B6

C0

C1

C2

C3

C4

C5

C6

D0

D1

D2

D3

D4

D5

D6

Enestamatriztenemos4lneasydentrodecadaunahay7campos,desdeelcampo0al
6.
Estonosrecuerdaquepodemoscargarestamatrizdentrodeunarraybidimensional,el
cualestudiamosenelcaptulo3.5.
Arazdequenoencontrenlaredgrande(elmaestroInternet)ningnmtodoqueme
ayudaraaordenarunamatrizdedatos,omejordicho,unarraybidimensionalpormediodel
nmerodelelementoqueyolepasaracomoargumento,decidconstruirunmtodosimple
deOrdenamientodeunamatrizpormediodelalgoritmodeMaza:
$campo = 2;
@array = sort {
($a->[$campo] <=> $b->[$campo])
||
($a->[$campo] cmp $b->[$campo])
} @array;

# nmero de campo a ordenar


# desde 0 hasta n
# comparamos nmeros y los
# ordenamos de mayor a menor.
# o si no son nmeros...
# comparamos caracteres y los
# ordenamos de mayor a menor

Sibiencadaunodeestosmtodossonconocidosportodos,habaquejuntartodopara
lograrrealizarelpropsito.
Dejoallectorunejemplodeusoparaquejuegueconelyestudiarsucomportamiento.
#!/usr/bin/perl
$arrayref = [
['Casa', 'Carro', 'Moto'],
[24, 89, 500],
['Perro', 'Gato', 'Caballo'],
['Calle', 'Ciudad', 'Pais'],
[22, 303, 405]
];

Pag.157

HugoMazaM.Perlbsicodesdecero
$campo = shift;
@{$arrayref} = sort {

# de-referenciacin

($a->[$campo] <=> $b->[$campo])


||
($a->[$campo] cmp $b->[$campo])
} @{$arrayref};

# de-referenciamos

# comparamos nmeros y los


# ordenamos de mayor a menor.
# o si no son nmeros...
# comparamos caracteres y los
# ordenamos de mayor a menor

for $i ( 0 .. $#{$arrayref} ) {
for $j ( 0 .. $#{$arrayref->[$i]} ) {
print $arrayref->[$i][$j] , "\t";
}
print "\n";
}
exit;

Comopodemosver,elscriptdeberecibirunargumento,quepodamospasaralscript
fcilmenteenlalneadecomandosejecutandoelscriptseguidodeunespacioyelnmero
decampoporelquedeseamosordenarlamatrizdedatos:
user@host:~$ ./ordenar.pl 0

Lalneaanteriorordenarlamatrizsegnelcampo0,laprimercolumna
user@host:~$ ./ordenar.pl 2

Ylaanteriorlneaordenarsegnelcampo2,latercercolumna.
Ejemplosdelosresultados:
user@host:~$ ./ordenar.pl 2
Perro Gato
Caballo
Casa
Carro Moto
Calle Ciudad Pais
22
303
405
24
89
500
user@host:~$ ./ordenar.pl 1
Casa
Carro Moto
Calle Ciudad Pais
Perro Gato
Caballo
24
89
500
22
303
405

Pag.158

Conejemplossencillosparaautomatizacindetareasenservidores

Pag.159

HugoMazaM.Perlbsicodesdecero

Pag.160

Conejemplossencillosparaautomatizacindetareasenservidores

Crditos:
TextodellibroManualdePerlbsicodesdecero:
HugoMazaMoreno
Dromedariodeportada:
CarlosAngelContrerasEscajeda
Indautor.Mxico.Mayo2010.
Abrilde2009Septiembrede2009
Revisinfinalparapublicacin:Febrerode2010
Fechadepublicacindeestaversin:20Abrilde2010
Pag.161

HugoMazaM.Perlbsicodesdecero

Pag.162