A Perl Script Nyelv
1973
Ken Thompson
megalkotja a grep
parancsot, melyben az ed
szövegszerkesztő parancsai és beépített
reguláris kifejezései egy külső programban
valódulnak meg, a Global REgular expression Print-ben.
1977
Alfred V. Aho, Peter
J. Weinberger, és Brian W. Kernighan
megalkotja az awk
számítógépes nyelvet. Az awk a Perl elődjének tekinthető.
1987
Dec.
18-án Larry Wall felteszi a
hálózatra a Perl 1.000-át,
és azonnal több ezer önkéntes
hozzálát teszteléséhez és
fejlesztéséhez. Larry Wall egy
fájlarhíváló és hibajelentő
rendszert szeretett volna megíni awk-ban, de az kevésnek
bizonyult a problémához. Lusta programozó
révén azonnal írt egy megfelelőbb
programzási nyelvet.
NAME
perl | Practical Extraction and Report Language
(gyakorlati kivonatolás és jelentés nyelv)
SYNOPSIS
perl [options] filename args
LEÍRÁS
A Perl egy parancsértelmező nyelv, melyet arra optimalizál-
tak, hogy átfésüljön egy tetszőleges szövegállományt, azok-
ból információt szedjen össze, és ennek alapján egy jelen-
tést nyomtasson ki. Igen hasznos nyelv számos rendszer kar-
bantartó feladatra is. Fő előnye inkább a gyakorlati alkal-
mazhatósága (könnyű használni, hatékony, teljes), mintsem
mintsem a szépsége (tömör, elegáns). A szerző véleménye sze-
rint magába ötvözi a C, sed, awk és sh legjobb tulajdonsága-
it, így azok számára, akik járatosak e nyelvekben, nem okoz
nagy nehézséget használata. A kifejezések szintaxisa nagyon
hasonlít a C nyelvére. Amennyiben olyan problémánk van,
melyet általában a sed, awk, vagy sh scriptekkel oldanánk
meg, de meghaladja azok lehetőségeit, vagy azoknál gyorsab-
ban szeretnénk futtatni, de nem óhajtuk a programot C-ben
megírni, akkor a perl a helyes választás. Rendelkezésre áll-
nak fordítóprogramok is, melyek a már meglevő sed és awk
programjainkat átírják perl-be.
Mivel kicsit rendetlen a formátuma, szokás a Perl-t még Patologikusan
Eklektikus Rendetlenség Listázónak is nevezni. A
szerző ezt is hivatalosnak tekinti.
#!/usr/bin/perl -w
print join " ", reverse split ' ', "hacker, Perl another Just"
1988
Június
5-én kijön a Perl 2.000.
- Reguláris kifejezések kiterjesztése
- Lokális változók
- Rekurzív eljárások
- A
sort
operátor
- ...
(Nov 3-án
Robert Tappan Morris megfertőzi a
hálózatot az első féreggel).
1989
Okt. 18-án
megjelenik a Perl
3.000, és első ízben a GNU Nyilvános
Licensz alapján
- bináris adatok kezelése
- változók átadása címük
szerint
- debugger bővítés
- a vektorok listává lehet alakítani és
viszont
- a szubrutinok a nevükkel hívhatók (mint a
C-ben)
- Új függvények:
mkdir
és rmdir
,
getppid
, getpgrp
és setpgrp
,
getpriority
és setpriority
, chroot
,
ioctl
és fcntl
, flock
,
readlink
, lstat
, rindex
, pack
és unpack
, read
, warn
,
dbmopen
és dbmclose
, dump
,
reverse
, defined
, undef
.
1990
Guido van Rossum (CWI,
Amsterdam) megalkotja a Python
nyelvet.
Convex
beépíti a Perl-t
a sztenderd operációs rendszerébe.
1991
Márc.
21-én megjelenik a Perl 4.000,
mind a GNU
Nyilvános Licensz mind az Artistic licensz alapján.
Megjelenik a Linux GNU
Nyilvános Licensszel.
1992
Januárban
megjelenik a Perl MacIntosh verziója, a
MacPerl, 4.0.2.
Decemberben felvetődik
egy, a TeX mintájára szerveződő
(Comprehensive TeX Archive Network -- CTAN)
arhíváló rendszer
létrehozásának gondolata: CPAN -- Comprehensive
Perl Archive Network.
1994
Okt. 18-án
megjelenik a Perl
5.000, teljesen újraírják a Perl-t.
- Objektumok.
- Dokumentáció:
perldoc
és pod
.
- A csomag elválasztó karakter
::
-ra módosul
.
- Új függvények.
- ...
1995
Rasmus Lerdorf
megalkotja a Perl
CGI szkriptet, mely egy HTML dokumentumban
információt gyűjtött a
látogatókról, és azt beleírta a HTML
dokumentumba.
Megalakul hivatalosan
a CPAN.
1996
Doug MacEachern
megalkotja a mod_perl-t,
mely beépíti a perl értelmezőt
az Apache web kiszolgálóba.
1997
Kijön a Perl 6.
A Perl megjelenik
Windows platformon is (ASP, OpenPerl)
2001
Open Cola
1.0 is the first open source consumer product and
sports the following Perl code on the can: (24 April)
#!/usr/bin/perl
open CAN, "excitedly";
join ($can, $mouth);
while ($colaRemaining > 0)
{if ($reallyThirsty) {$chug;} else {$sip};}
dumpIN_RECYCLING_BOX;IN_RECYCLING_BOX;
Egyéb Linkek
Támogatott
Operációs rendszerek
- Unix
- Macintosh - (OS 7-9 és X).
- Windows.
- VMS
- és sokan mások...
Perl főbb
tulajdonságai
- a C,
awk, sed, sh, BASIC stb. legkényelmesebb tulajdonságait
tartalmazza.
- a DBI-n (database integration interface) (DBI) keresztül
támogatja más gyártók
adatbáziskezelőit, mint Oracle, Sybase, Postgres, MySQL, stb.
- együttműködik a HTML, XML és egyéb
hipertext nyelvekkel.
- támogatja a Unicode-t.
- támogatja mind az eljárás- mind az
objektorientált programozást. s
- hozzácsatolhatók a külső C/C++
könyvtárak (XS vagy SWIG-en keresztül).
- bővíthető, a CPAN-ról több, mint 500 modul
letölthető.
- más rendszerekbe integrálható.
Perl és a Web
- a Perl (ASP) a
legnépszerűbb web programozási nyelv adatkezelése
és gyors fejlesztési lehetősége miatt.
- az Internet
"gyorstapasza".
- CGI.pm
modulján keresztül egyszerűsíti a HTML formák
kezelését.
- kezeli a
titkosított Web adatokat, pl. kereskedelmi tranzakciókat.
- Web szerverekbe
integrálásával jelentős
sebességnövekedést lehet elérni.
A Perl célja
A Perlt
programozóknak tervezték, általános
feladatokhoz, melyek túl nehezek vagy túl
hordozhatóságérzékenyek a shell
számára, és túl bonyolult azokat C-ben vagy
más UNIX ragasztónyelven kódolni.
A Perl működése
A Perl a futtatandó
programot először teljes egészében beolvassa
és értelmezi, majd ha azt hibátlannak
találta, akkor kezd neki a futtatásnak. Ezáltal
előfeldolgozza a scriptet, és jelentősen gyorsítja a
futását egy egyszerű értelmező scripthez
képest. (Természetesen terjedelmes, rövid ideig
futó program esetén ez pont fordítva van, az
értelmezés sokkal hosszabb ideig tarthat, mint a program
futása).
A Perl program alapszerkezete
#!/usr/bin/perl -w
- a tokenek közötti elválasztó karakterek
(szóköz, tabulátor, újsor)
opcionálisak (akár a C-ben)
- az egyes függvényhívásokat pontosvessző
választja el (akár a C-ben)
- a C-vel ellentétben nincsen fő rutin, a shell scripthez
hasonlóan az állomány utasításai egy
nagy végrehajtási rutint képeznek
- a megjegyzések a shellhez hasonlóan a # karaktertől
az újsor karakterig tartanak.
Hello world
#!/usr/bin/perl
print "Hello world!\n";
# Használható a C mintájára a zárójeles argumentumátadás is.
print ("Hello world!\n");
# Használható a C mintájára a formázó karakterek is.
printf("%20s\n","Hello world");
Változók
- skaláris változók:
- $-al kezdődnek: $nev,
$valtozo (betűk, számok, aláhúzás jel)
- tartalmazhatnak számot, karakterláncot. A Perl
nem különbözteti meg ezeket, kontextustól
függően értelmezi a típusukat.
- belsőleg a számokat a Perl dupla pontos valós
számként kezeli
- az oktális számok 0-val kezdődnek
- hexadecimális számok 0x-el kezdődnek
$szam1 = 0377;
$szam1 = -0xff;
print "szam1=$szam1, szam2=$szam2\n";
eredménye
szam1=255, szam2=-255
- a karakter egy 8 bites érték a teljes 256 karakteres
készletből (a nullát is beleértve)
- a karakterlánc hosszát csak a memória
nagysága korlátozza (nincsenek beépített
korlátok)
- szimpla idézőjeles karaktersorozat
- csak a \' és \\ bír kitüntetett
jelentéssel, a 'hello\n'
a hello, backslash és n
betűkből áll, a \n nem
jelent újsort!
- a 'don\'t' a don't sorozatot kódolja
- az újsort egy explicit sortöréssel
tehetjük a karakterláncba
- dupla idézőjeles karaktersorozat
- a C szintakszisát követi, a backslash
kódolja az utána következő karaktert
- "hello\tvilág"
a hello és a világ közé tabulátort tesz
\n
|
újsor
|
\r
|
kocsi vissza
|
\t
|
tabulátor
|
\f
|
lapdobás
|
\b
|
backslash
|
\a
|
csengő
|
\e
|
escape
|
\ddd
|
ASCII
érték (oktális)
|
\xhh
|
hexadecimális
érték
|
\cC
|
CTRL+C (C helyett
más is állhat)
|
\\
|
backslash
|
\"
|
idézőjel
|
\l
|
a következő betű
kisbetűs
|
\L
|
kisbetűsre
váltás \E-ig
|
\u
|
a következő betű
nagybetűs
|
\U
|
nagybetűsre
váltás \E-ig
|
\Q
|
minden nem alfanumerikus
karaktert elé backslash-t gondol \E-ig
|
\E
|
\L, \U és \Q
lezárása
|
- visszafelé idézőjeles karakterláncok
- lefuttatja mint egy shell parancsot, és a parancs
kimenetét menti el a változóba
- $lista = `ls -l`;
- Műveletek
- számokon: összeadás, kivonás,
szorzás, osztás, hatványozás (2.3**3.4),
modulus (10 % 3)
- karakterláncokon: .
(pont) az összefűzés: "Hello "."world", szorzás
"szó" x 3
eredménye "szószószó"
- (3+2) x 4 eredménye "5555"
- "X" . (4*5) eredménye "X20"
- Összehasonlítás:
|
Numerikus
|
Karakterlánc
|
egyenlő
|
==
|
eq
|
nem egyenlő
|
!=
|
ne
|
kisebb, mint
|
<
|
lt
|
nagyobb. mint
|
>
|
gt
|
kisebb vagy egyenlő
|
<=
|
le
|
nagyobb vagy egyenlő
|
>=
|
ge
|
- definiálatlan érték:
defined($a)
- Tömbváltozók:
- @-al kezdődnek, a
tömb egy változó, mely egy listát (rendezett
skaláris adat) tárol. A tömb minden eleme egy
külön skaláris változó. A
tömböknek tetszőleges számú eleme lehet
(amíg a memória bírja).
- lista: (1,2,3) vagy ("kalap",5.2) vagy (1 .. 5) vagy (0,1.2 .. 5.2,6) vagy ($a .. $b)
- @a = ("kalap", "kabát",
"sál"); vagy @a =
qw(kalap kabát sál);
- kiíratás: print
("A lista: ",$b,"\n"); is egy tömb!
- A @a és $a két
különböző dolog!
- @a tömb elemei: $a[0], $a[1], ... az elemek
már skalárok!
- Részelemek
- @a[0,7,5]
# ugyanaz mint ($a[0],$a[7],$a[5])
- @a[0,1] =
@a[1,0]
# felcseréli a tömb első két elemét
- @a[2,3,5] =
@b[1,4,6]
# értékadás a megfelelő elemekre
- ($b,@a) =
($c,$d,$e)
# $b=$c; @a=($d,$e);
- @a = qw(kalap kabát sál)[1,2]; #
@a=qw(kabát
sál);
- $b =
@a;
# $b az @a hossza
- ($b) =
@a;
# $b=$a[0];
- @a = qw(kalap kabát sál); @b=(2,1,0);
@vissza=@a[@b]; # megfordítja a sorrendet.
- $a[-1] az utolsó, $a[-2] az azelőtti, stb. elemre
hivatkozik
- $#a az utolsó elem
indexszámát adja meg
- a tömbnek nincsen előre definiált hossza
- push @a,$b; # a tömb
végére teszi a $b
értéket
- $b = pop @a; # leszedi a tömb
végén levő értéket, és a $b-be teszi.
- $b = shift @a; # a tömb elején
levő értéket szedi le a tömbből és teszi $b-be.
A függvények argumentumai is tömbben vannak,
így a shift
segítségével
lehet az egymás utáni argumentumokat skaláris
változókba menteni.
- unshift @a,$b; # a tömb elejére teszi
a $b értéket
- @b = reverse @a; # megfordítja az @a tömb
elemeinek sorrendjét;
- @b = sort @a; #
növekvő ASCII (nem
numerikus) sorrendbe teszi az @a tömb elemeit.
- @b = chomp @a; # a tömb minden
eleméből eltávolítja a
rekordelválasztó karaktert (újsort).
Skaláris változóra is működik.
- A tömb elnevezése megegyezhet egy skalár
nevével:
- Hash (asszociatív tömb)
- Olyan tömb, melynek elemei skaláris
értéket vesznek fel, de az indexértékek nem
természetes számok, hanem tetszőleges skalárok. A
hash valójában egy kulcs-érték pár.
- %-al kezdődnek, hogy
megkülönböztessük őket
a skalár és tömb változóktól. A
hash elnevezése megegyezhet egy skalár
vagy tömb nevével:
-
$a="ez egy string";
@a=(1,2,"aha");
$a{"kulcs"}="érték";
$a{3.1415}=2.7172;
print "\$a=$a, \@a=@a\n";
foreach $ind (keys %a) {
print "a{$ind} = $a{$ind}\n";
}
$a=ez egy string, @a=1 2 aha
a{kulcs} = érték
a{3.1415} = 2.7172
- A Perlnek nincsen literális
ábrázolása a hash számára (kezdeti
értékadás, listázás), de egy
páros számú elemből álló
listát oda-vissza tud hash-é konvertálni. Az
előbbi példában a
-
@b = %a;
print "@b\n";
kulcs érték 3.1415 2.7172
kimenetet eredményez.
-
@b = ("egy",1,"kettõ",2,"három",3);
%a=@b;
pedig egy $a{"egy"}=1; $a{"kettõ"}=2; $a{"három"}=3
hash-t eredményez.
- A
reverse
megfordítja a kulcsokat
és az
értékeket, azaz a %c = reverse %a; a $c{1}="egy";
$c{2}="kettõ"
és $c{3}="három"
hozzárendelést tartalmazza. Ha két azonos
érték volt, abból csak egy kulcs lehet egy
értékkel (a hash tartalmazza az összes
értéket, de a $a{"kulcs"}
hivatkozás
megjósolhatatlan, hogy melyik értéket adja vissza).
- A
keys
a hash kulcsait adja meg, a @b =
keys %a;
lista az ("egy",
"kettõ", "három")
értékeket
tartalmazza.
- A
values
a hash értékeit adja meg,
a @b = values %a;
lista az (1, 2, 3)
értékeket
tartalmazza.
if(%a)
vagy if(keys(%a))
# %a
nem üres
while (keys(%a) < 10)
#
amíg %a
-nak 10-nél kevesebb eleme van
foreach $index (keys(%a))
# %a
összes
kulcsára ciklus, ahol az $index
egymás
után
felveszi a kulcsokat.
- Az
each
a hash kulcs-érték
párjával tér vissza: while
(($kulcs,$ertek) = each(%a)) {}
.
- A
delete
kitöröl egy
hozzárendelést a hash-ből: delete
$a{"kettő"};
.
Vezérlési szerkezetek
- if (feltétel) { ...
}
# kötelező kitenni a {} zárójeleket, még
akkor is, ha csak egy utasítás van bennük!
- if (feltétel) { ... } else { ...
}
# a 0, "" és undef értékek mindig hamisak
- unless (feltétel) { ... } else { ... }
- if (feltétel) { ... } elseif { ... } elseif { ... } ...
else { ... }
- while (feltétel) { ... }
- until (feltétel) { ... }
- do { ... } while
(feltétel)
# legalább egyszer lefut a ciklus
- do { ... } until (feltétel)
- for (kezdeti kifejezés; feltétel; új kezdeti
kifejezés) { ... } # megegyezik a C for
ciklusával: for(i=0;i<10;i++) { ... }
- foreach $skalár @lista { ...
}
# a lista minden elemére végrehajta a ciklust a
következő elemet a $skalárba helyettesítve.
Listának megadhatunk kifejezéseket, valamint hash-eket is:
foreach $i (reverse @a) { ... }
foreach $i (values %a) { ... }
@a = (3,5,7,9); foreach $i @a {$i *= 3;}
eredménye:
(9,15,21,27).
# feature, not bug!
- last: while (feltétel) { ... if(feltétel)
{...; last;} ... } # kilép a
legkülső zárt ciklusból (C break
utasítás). Csak a for, foreach, while, until
számít ciklusnak, az if és do {...} while/until nem számít ciklusnak!
- next: while (feltétel) { ... if(feltétel)
{...; next;} ... } # nem fejezi a maradék
utasítások, a ciklust a következő
értékkel újrakezdi. (C next utasítás)
- redo: while (feltétel) { ... if(feltétel) {...;
redo;} ... } # a ciklus elejére ugrik,
nem értékeli újra a feltételt!
- { ... if(feltétel) {...; last;} ...
redo;}
# while-szerű ciklus, amíg a feltétel nem teljesül,
ciklust hajt végre.
- CIMKE: while (feltétel) { ... if(feltétel) {...;
last CIMKE;} ... } # A címke csupa nagybetűből és
számból áll (Ebben az esetben ugyanaz a
hatása, mint az argumentum nélküli last parancsnak,
több, egymásba ágyazott ciklus esetén mondja
meg, hogy melyik szinten hagyjuk abba a ciklust).
- Kifejezésmódosító: kifejezés if feltétel.
ITT: while (feltétel) { ...; last ITT if ($a>0); ... }
Először mindig a feltétel
értékelődik ki, és aszerint
hajtódik végre a kifejezés.
- $n=431; $i=1; $i *= 2 until
$i>$n;
# megkeresi az első $n-nél nagyobb kettő hatványt.
- && és || # A
C-hez hasonló struktúra, ÉS/VAGY. ÉS
esetén addig értékeli ki balról jobbra a
kifejezéseket, amíg hamisat nem talál (vagy el nem
fogytak a kifejezések), VAGY esetén amíg az első
igaz kifejezést meg nem találta:
- $a=<STDIN> &&
chomp($a)
# ha be tudott olvasni egy sort, akkor levágja az újsor
karaktert.
- open FILE,"file" || die "Baj
van!";
# ha nem tudja megnyitni a file áományt olvasásra,
hibaüzenettel kilép.
Input/Output
- $a =
<STDIN>;
# beolvasás a standard bemenetről, az újsor karaktert is
beleértve.
- while (defined($a = <STDIN>)) { ... } #
beolvassa a file végéig (^D)
- while (<STDIN>) { chomp; ... } #
beolvasás a $_
változóba,
az újsor karakter törlése, ...
- while (<>) { print $_;
}
# az perl script argumentumban megadott
állományokból olvassa be a sorokat. Az
argumentumokat a perl az @ARGV
tömbben tárolja, így "be is lehet csapni" a
parancsot:
- @ARGV=qw(file1 file2 file3); while (<>) { print $_;
} # gyors és csúnya
programozás
- SOR: while (<STDIN>) { last SOR if /^From: /;
}
# addig olvassa be a standard bemenetet, amíg a From: -al
kezdődő sorhoz nem ér.
- kiíratás az STDOUT-ra: print és printf
- Fájlkezelők használata:
- open
INP,"file";
# megnyitja a file-t olvasásra
- open
OUT,">file";
# megnyitja a file-t írásra (felülírja, ha
létezik)
- open
OUT,">>file";
# megnyitja a file-t hozzáfűzésre
- close
OUT;
# lezárja a file-t (a perl kilépéskor ezt
automatikusan megteszi)
$ki="passwd.mentes";
open (EP,"/etc/passwd") || die "File: /etc/passwd, $!";
open (KI,">$ki") || die "File: $ki, $!";
while (<EP>) {
chomp;
print KI "/etc/passwd: $_\n";
}
close KI;
close EP;
- A print (printf) után közvetlenül, vessző
nélkül megadhatjuk a fájlkezelőt, amihez
tartozó fileba irányul az írás. Az alap
fájlkezelő a STDOUT
- A shell-hez hasonlóan vizsgálható egy
állomány megléte, írhatósága,
stb.:
- if (-e "index.html" || -e "index.asp") {
...} # igaz, ha vagy az
"index.html" vagy az "index.asp" létezik.
- néhány kapcsoló
-r
|
a fájl vagy
könyvtár olvasható
|
-w
|
a fájl vagy
könyvtár írható |
-x
|
a fájl vagy
könyvtár végrehajtható
|
-o
|
a fájlt vagy
könyvtárat a felhasználó birtokolja
|
-e
|
a fájl vagy
könyvtár létezik
|
-z
|
a fájl vagy
könyvtár létezik és nulla méretű
|
-s
|
a fájl vagy
könyvtár létezik és nem nulla méretű
|
-f
|
a bejegyzés egy sima
fájl
|
-d
|
a bejegyzés egy
könyvtár
|
-l
|
a bejegyzés egy
symlink
|
-T
|
a fájl szöveges
|
-B
|
a fájl bináris
|
-M
|
a
módosítás kora napokban
|
-C
|
a
hozzáférés kora napokban
|
$a = -M "test.pl";
$b = -M "hyphen.zip";
print "test.pl is $a days old, while hyphen.zip is $b days old\n";
eredménye: test.pl is
2.31481481481481e-05 days old, while hyphen.zip is 18.4712037037037
days old
if(-M "hyphen.zip" > 3) {...}
# ha 3
napnál régebben volt módosítva, akkor ...
Szabályos Kifejezések
A perl igazi erőssége a szabályos kifejezések
kezelése
if (/regex/) { ... } # ha a $_ egyezik a regex-el, akkor ...
a /regex/ valójában az m/regex/ (match)
rövidítése. Ha egy másik
változón akarjuk megnézni az egyezést,
akkor a
if ($a =~ /regex/) { ... }
Hasonlóképpen, a szokásos módon
elvégezhetőek a helyettesítések is
s/ab*c/def/; # a $_-ban az ab*c reguláris kifejezést helyettesíti def-el.
$a =~ s/ab*c/def/; # ugyanez az $a változóra
- A helyettesítés szokásos
opciói: g,i
használhatók.
- más határolójel is
használható: m@/etc/passwd/@
- [a-z] : a lokális
beállításoktól függ a karakterek
sorrendje, hol vannak a nemzeti karakterek, stb.
Kiterjesztett reguláris kifejezés
Példa: az egrep parancs:
A kiterjesztett reguláris kifejezés tartalmazza a
reguláris kifejezéseket , és
- metakarakterek
elveszítik jelentésüket a [] között: []$&%^-]
- legelsõ ]
jelenti a ] jelet (nem
lezárás)
- nem elsõ ^
jelenti a ^ jelet (nem
szó eleje)
- utolsó -
jelenti a - jelet (nem
tartomány)
- \n : n szám az n. egyezés
extrák:
- csoportok:
- [:alnum:]
[0-9A-Za-z]
- [:alpha:]
[A-Za-z]
- [:cntrl:]
kontroll karakterek, a [:upper:], [:lower:], [:alpha:], [:digit:],
[:punct:], [:graph:], [:print:], vagy [:xdigit:]
osztályokba nem sorolható karakterek.
- [:digit:]
számjegyek
- [:graph:]
grafikus karakterek
- [:lower:] kisbetűs
karakterek
- [:print:]
nyomtatható karakterek (kivéve a [:space:]
osztályt)
- [:punct:]
írásjelek: ! ' # S %
& ` ( ) * + , - . / : ; < = > ? @ [ / ] ^ _ { | } ~
- [:space:]
szóköz karakterek (szóköz, tab, újsor,
cr, ff)
- [:upper:]
nagybetűs karakterek
- [:xdigit:]
[0-9A-Fa-f] (hexadecimális karakter)
függetlenek a
locale beállításoktól és az ASCII
kódtáblától.
A szögletes
zárójelek az osztályelnevezés részei
így a keresésben duplán jelenik meg a
szögletes zárójel:
/[[:digit:]]/
# van benne számjegy
/[][:digit:]$&]/
# van benne ] vagy számjegy vagy $ vagy &
\w : [[:alnum:]]
\W : [^[:alnum:]]
\b :
\< vagy \> szóhatároló pozíció
\B : nem
szóhatár
- ismétlődés (a * jelen kívül)
- ?
: az
elõtte levõ karakter opcionális: egyszer vagy
nullaszor fordulhat elõ
- +
: az elõtte levõ
karakter legalább egyszer fordul elõ.
- {n}
: az
elõtte levõ karakter pontosan nszer
ismétlõdik
- {n,}
: az elõtte levõ karakter
legalább nszer
ismétlõdik
- {n,m}:
az elõtte
levõ karakter legalább nszer
de legfeljebb mszer
ismétlõdik
- | :
két reguláris
kifejezés vagylagos kombinációja
\b(ablak)\b|\b(ajto)\b
megkeresi, hogy hol fordul
elõ az
ajto vagy
ablak szó
magában.
- Az ismétlõdés
hamarabb értékelõdik ki, mint a reguláris
kifejezések összefûzése, mely viszont
megelõzi a |
mûveletet. Így a
kifejezés az ablak legalább egyszeri,
míg az ajto
legalább kétszeri elõfordulását
írja elõ. Az
(ajto)(ablak)|(ajto.*){2,}
viszont azt
követeli meg, hogy egy sorban az ajto-t
kövesse valahol az
ablak VAGY az ajto ketszer szerepeljen. A | az elõtte
levõ teljes kifejezést (reguláris
kifejezések összefûzése) kapcsolja össze
a mögötte álló reguláris
kifejezéssel.
- A zárójelekkel
megváltoztathatjuk a kiértékelési
sorrendet:
(ajto).*((ablak)|(ajto.*){2,})
az ajto
után
szerepeljen az ablak, vagy
két ajto string.
((ajto)|(ablak)).*\1
az ajto
vagy az ablak legalább
kétszeri elõfordulását írja
elõ.
- A kiterjesztett reguláris kifejezésekben ha a
? + * . { }
| ( ) ^ $ \
karaktereket keressük, akkor le
kell
õket védeni a \ jellel.
Míg egyszerû
reguláris kifejezésben a
\(ablak\)
kifejezés az
ablak stringet keresi,
és azt eltárolja, ugyanez
kiterjesztett reguláris kifejezésként a
zárójelekkel körbevett
ablak stringet keresi.
- Környezeti változók hatása
Alapesetben a
tartományok és karaktertípusok
kiértékelése az ASCII szekvencia alapján
történik (ez a C locale). Ha az
- LC_ALL, LC_COLLATE, LANG be
van állítva, akkor azok ebben a
kiértékelési sorrendben
megváltoztatják a tartományok
definícióját
- LC_ALL, LC_CTYPE, LANG a karakterek
típusát adják meg (mi a nem betû)
További
bővítések
perl, java, python, tcl ...
ld.
http://www.tropicsoft.com/Components/RegularExpression/SyntaxBcb3.htm
perl
\d
|
[0-9]
|
\D
|
[^0-9]
|
\w
|
[a-zA-Z0-9_]
|
\W
|
[^a-zA-Z0-9_]
|
\s
|
[ \r\t\n\f]
|
\S
|
[^ \r\t\n\f]
|
Zárójel
(csoportosítás)
|
( ) (?: )
|
Sokszorozók
|
? + *
{m,n} ?? +? *? {m,n}?
|
referenciapont
|
^ $
\b \B \A \Z (?= )
(?<= ) (?! ) (?<! )
|
váltakozás
|
|
|
- \b
szóhatár
- \B nincs
szóhatár
- (?: ) nem gyűjtő zárójel, a
benne levő kifejezés nem kerül bele az \n (n egy
szám) átmeneti változóba
- (?=teljes_szöveg)teljes csak akkor
illeszkedik a teljes-re, ha
az a teljes_szöveg
része. Egyenértékű a teljes(?=_szöveg)
kifejezéssel.
- (?<=\d) utóvizsgálat: az adott pont előtt
számjegynek kell állnia.
- (?! ) (?<! ) negatív elő- illetve
utóvizsgálat
- \A sor vagy
karakterlánc eleje
- \Z vagy \z sor vagy karakterlánc
vége
- ?? +? *? {m,n}? lusta kvantorok (a
legszűkebb egyezése veszik)
- ?+ ++ *+ {m,n}+ harácsoló kvantorok (a
normális mohó kvantornál is mohóbb
azáltal, hogy a közben előforduló opcionáis
kifejezéseket a feldolgozás során azonnal
elfelejti).
<B>ajtó</B> és <B>ablak</B>
szövegre a
/<B>.*</B>/ az ajtó</B> és <B>ablak -ra illeszkedik
/<B>.*?</B>/ az ajtó</B> -ra illeszkedik ugyanaz, mint /<B>((?!</?B>).)*</B>/
- /i nem
különbözteti meg a kis- és nagybetűket
- /x szabad beosztás (a
karakterosztályon kívüli whitespace karakterek nem
számítnak) és megjegyzés (a # után
sorvégig megjegyzés írható) regex
üzemmód
- /s pont-mindenre-illeszkedik
illesztési üzemmód (a pont karakter újsorra
is illeszkedik)
- /m fejlett sorhorgony illesztés
üzemmód (alapesetben a karakterláncban levő
újsor karaktert a ^ és $ figyelmen kívül
hagyja, a /m logikai sorokat definiál, minek
következtében a ^ és $ a logikai sor elejét,
illetve végét jelenti.)
- /g globális
helyettesítés
- /o ne értékelje ki
újra a regex-ben levő változókat (az első
hívás kiértékelését
befagyasztja). A perl rekurzívan értékeli ki a
regex-et, amíg nem változik a tartalma.
- /e a helyettesítő
karakterláncra lefuttatja az eval
függvényt. A módosító
ismételhető, ekkor annyiszor futtatja le a perl az eval függvényt,
ahányszot a módosító megjelenik
$pat = shift;
while (<>) {
print if /$pat/o;
}
$string = "Placido P. Octopus";
$regex = "P.";
$string =~ s/\Q$regex/Polyp/;
Ezek regex-en belül is ki-be kapcsolhatók:
<B>(?i:nagyon)</B> # a nagyon állhat kis és nagy betúkből is.
Példa:
1. helyettesítsük az összes Jeffs kifejezést
Jeff's -re
s/\bJeffs\b/Jeff's/g;
# a triviális megoldás
s/\b(Jeff)(s)\b/$1'$2/g;
# ugyanez csoportokkal
s/\bJeff(?=s\b)/Jeff'/g;
# elővizsgálattal
s/(?<=\bJeff)(?=s\b)/'/g;
# elő- és utóvizsgálattal
s/(?=s\b)(?<=\bJeff)/'/g;
# ugyanaz, mint az előző
2. Csoportosítsuk egy egész szám
számjegyeit hármas csoportokba
while ( s/(\d)((\d\d\d)+\b)/$1,$2/g) {}
3. szűrjük ki az ismétlődő szavakat egy HTML szövegben
(lehet közben <parancs>, </parancs> alakú
kifejezés is!)
$/ = ".\n"; # a beolvasásnál a . vagy az újsor a rekordhatár
while (<>) {
next if !s/\b([a-z]+)((?:\s|<[^>]+>)+)(\1\b)/\e[7m$1\e[m$2\e[7m$3\e[m/ig;
s/^(?:[^\e]*\n)+//mg; # A jelöletlen sorok eltávolítása
s/^/$ARGV: /mg; # Az állománynév beszúrása a sorok elejére
print;
}
A
tr
parancs
- tr/ab/ba/; # az előszőr megadott
karakterlánc minden karakterét a második
karakterlánc megfelelő karakterére cseréli. Ha
a második karakterlánc rövidebb, akkor annak
utolsó karakterét ismétli addig, amíg
azonos hosszakat nem kap.
- tr/áéíóöőúüű/aeiooouuu/;
# ékezettelenítés
- $_="szól a kakukk"; tr/a-z/x/; # "xxxx
x xxxxxx" a fel nem sorolt karaktereket (pl. szóköz)
nem változtatja.
- A /d opcióval a második karakterláncban
hiányzó betűket törli (nem egészíti ki
a megfelelő számú karakterre az utolsó
karakterrel):
$_="fred and barney"; tr/a-z/ABCDE/d;
# "ED AD
BAE"
$_="szól a kakukk"; $szamlalo = tr/a-z//;
# nem
változtatja meg a stringet (/a-z/ egy karakterosztály),
de megszámlálta a betűk számát benne.
- A /c opcióval megfordítjuk a
helyettesítést: minden nem felsorolt karakterre
történik
$_="szól a kakukk"; $szamlalo =
tr/a-z//c;
# nem változtatja meg a
stringet,
de a szamlalo értéke 2
$_="szól a kakukk"; tr/a-z/_/c;
#
"szól_a_kakukk"
- $_="szól a kakukk"; tr/a-z//cd; #
"szólakakukk" : törölte a "nem betűket"
- A /s opció a kicserélt láncban az
egymás után következő azonos karakterek
közül csak egyet tart meg.
$_="aaabbbcccdeffghii";
tr/defghi/abcddd/s;
# "aaabbbcccabcd"
$_="szól
a
kakukk";
tr/a-z/_/cs;
#
"szól_a_kakukk"
Függvények
- felhasználói függvény (sub, shift,
return)
- return($a,$b,@lista);
- my $valtozo;
- local $valtozo;
$ertek="eredeti";
kiir();
kiir_svindli();
kiir_my();
kiir();
sub kiir_svindli {
local ($ertek) = "átmeneti"; # megváltoztatja az innen induló hívásokra is
kiir();
}
sub kiir_my {
my $ertek = "saját"; # csak a rutinon belül érvényes, a hívásokra már nem
kiir();
}
sub kiir {
print "Az aktuális érték $ertek\n";
}
eredménye:
Az aktuális érték eredeti
Az aktuális érték átmeneti
Az aktuális érték eredeti
Az aktuális érték eredeti
sub rutin() {
arg1 = shift;
arg2 = shift;
...
return ($status,$szam,@lista);
}
....
($status,$n,@a) = rutin($a,$b,$c); # meghívja a
rutint $a,$b,$c argumentumokkal
($status,$n,@a) =
&rutin;
# meghívja a rutint a @_ argumentumokkal
$fuggveny="rutin";
($status,$n,@a) = &$fuggveny($a,$b); # indirekt
hívás név szerint
$fuggveny=\&rutin;
($status,$n,@a) = &$fuggveny($a,$b); # indirekt
hívás referencia szerint
sub rutin($$;$) { # két kötelező skalár
és egy opcionális skalhívr argumentum
...
}
sub rutin1(@;@)
{
# egy kötelező és egy opcionális lista argumentum
(nincs értelme)
@ta = @_;
print "a=@ta\n";
}
sub rutin2($;$)
{
# egy kötelező és egy opcionális skalár
(lista referencia) argumentum
$pta = shift;
@ta = @$pta;
$ptb = shift;
@tb = @$ptb;
print "a=@ta\n";
if(defined(@tb)) {print "b=@tb\n";}
}
@a=(1,2,3);
@b=(4,5,6);
rutin1(@a,@b);
# az (@a,@b) listával hívja meg
rutin2(\@a,\@b);
# referncián át adja át az a és b
tömböket
rutin2(\@b);
- sort (numerikus)
- sort { $a <=> $b } @lista;
#numerikus
- sort { $a cmp $b } @lista; # karakteres
- sort my_function @lista; sub my_function { $a <=>
$b }
- sort { $nevek{$a} cmp $nevek{$b} } keys(%nevek);
- sort { ($a <=> $b) ($a cmp $b) }
@lista; # ha numerikus valamelyik akkor az első
feltétel 1-et vagy -1-et ad, ha egyik sem numerikus, akkor a
<=> 0-t ad, és a második
összehasonlítás hajtódik végre.
- sort { ($nevek{$a} cmp $nevek{$b}) ($a cmp $b) }
keys(%nevek); # azonos érték esetén a kulcs
szerint rendez
- @ertekek=(1,3,5,7,11,13,17,19,23,29,31,37); rand(@ertekek); # a
lista egy véletlenszerűen kiválasztott elemével
tér vissza.
- srand;
- @lista=split(/\t/);
@lista=split(/\s+/,$valtozo); split megegyezik a split(/\s+/,$_)
-vel
- $valtozo=join(";",@lista); nem szabályos
kifejezés, hanem karakterlánc az első argumentum
- join(":","",@lista); #
("",@lista) listára végzi el: az első elem elé is
tesz :-t
- join(":",@lista,""); #
utolsó elem után is tesz :-t
- $i=index($karakterlánc,$alkarakterlánc);
# $alkarakterlánc helye a $karakterlánc-ban, 0-val kezdve
- ha nincs találat, -1-et ad.
- rindex()
# ugyanaz, mint az index, de jobbról keresi az első
előfordulást.
- $s=substr($karakterlánc,$kiindulás,$hossz)
- $karakterlánc=sprintf("formátum",változók);
# ld. C sprintf függvény
- die:
az argumentumban szereplő listát kiírja a standard
hibakimenetre és kilép a programból
(kivételt dob).
- Ha a lista újsorra végződik nem írja ki a
file nevét és a sor számát, ahol a die
történt
- A $! tartalmazza az
utolsó operációs rendszerbeli hiba szöveges
leírását.
open (INP,"valami") || die "Nem jött össze:
$!";
a Nem jött
össze: No such file or directory at ./test.pl line 3.
hibaüzenetet adja.
- warn:
a
die
-hoz hasonlít, csak nem szakítja meg a
program
futását.
- exit
- chdir("dir");
# útvonalat vált
- @a =
glob("/etc/*.conf");
# létrehozza a "/etc/*.conf" mintának megfelelő
állományok listáját
- opendir(DIR,"dir");
# megnyitja olvasásra a "dir" könyvtárlistát
- while ($dir=readdir(DIR)) {
...} #
beolvassa a
DIR-hez tartozó könyvtár állományneveit
- closedir(DIR);
# bezárja a DIR könyvtárkezelőt
- mkdir("dir"); # listát is
elfogad
- rmdir("dir"); # listát is elfogad
- unlink("file"); # listát is elfogad
- foreach $file (<*.c>) { ... }
- foreach $file (<*.dvi>) { unlink($file) || warn "gond van a
$_ törlésével: $!"; }
- rename("fileregi","fileuj"); # Nem tud más
eszközre átmozgatni, és a fileuj-nak mindig
tartalmaznia kell a fájlnevet (más könyvtárba
való mozgatáskor is, nem elég a
könuvtárnév, mint a shellben!)
- link
"file","link";
# hard link = ln file linki
- symlink "file","link"; #
szimbolikus link = ln -s file link
- chmod(0644,"file1","file2",...,"fileN");
# chmod 0644 file1 file2 ... fileN
- $uid=1234; $gid=35; chown($uid,$gid,"file1","file2", ...,
"fileN");
- stat()
# állományok tulajdonságainak listája.
Hasonlít a C függvényhez. ld. perldoc -f stat
- $status=system("shell parancs"); # egyszavas
argumentum esetén kikerüli a shellté ld. C system
hívás
- exec("parancs");
# kilép a perl scriptből, és lefuttatja a parancs-ot.
- $pid=fork();
# C fork hívás, a szülő processz megkapja a gyermek
pid-jét, a gyermek 0-t
- open
PIPE,"|program";
# megnyitja a programot és a bemenetét a PIPE-hoz rendeli
- open
PIPE,"program|";
# megnyitja a programot és a kimenetét a PIPE-hoz rendeli
Beállított változók
perldoc perlvar
- @ARGV parancssor argumentumok. Az $ARGV[0] a script neve.
- $#ARGV az argumentumok száma
- $#a a tömb legmagasabb indexe
- $ARGV a feldolgozás alatt álló
állomány neve
- @_ a szubrutinnak átadott paraméterek
listája
- %ENV (hash)
- $_ vagy $ARG alapértelmezésbeli
input/output
- $! vagy $ERRNO hibaüzenet
- $n (n egy szám) a
mintafelismerésnél az n. mintát tárolja
- $* nem nulla értéke esetén
többsoros keresést végez (nem zárja le a
keresést a sor végén). A ^ és $ regex
hatását módosítja
- $. vagy $NR az utoljára használt
állománykezelőben az aktuális sor száma
- $/ vagy $RS bemeneti rekord határoló
(újsor, több karaktert is tartalmazhat, de nem lehet
szabályos kifejezés).
Megváltoztatásával egyszerre több sort is
beolvashatunk. A $/=""; sor
hatására az üres sorokig terjedő blokkokat olvas be
a perl.
- $, vagy $OFS kimeneti mezőhatároló
- $\ vagy $ORS kimeneti rekord határoló
(alapesetben üres: nem tesz ki újsort).
- $| nem nulla érték esetén flush-t hajt
végre minden írás után
- $? az utolsó pipe vagy `parancs` vagy system()
státusza
- $$ processz azonosító
- $< vagy $UID valódi felhasználói
azonosító (uid)
- $> vagy $EUID effektív UID
- $( vagy $GID valódi csoportazonosító
(gid)
- $) vagy EGID effektív gid
- $0 a program neve
- $[ egy tömb vagy egy karaktersorozat első elemének
indexe (alapesetben 0)
- $] a Perl verziószáma + patchlevel (pl. 3.019)
Példák
- karakterkonverzió
(utf8 -> latin1)
# U-00000000 - U-0000007F: 0xxxxxxx
# U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
# U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
# U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx etc.
# pl. c3 a4 = 11000011
10101000
-> 00011101000 = e4 -> ä
while (<INP>) {
chomp;
s/([\xC2\xC3])([\x80-\xBF])/chr(ord($1)<<6&0xC0|ord($2)&0x3F)/eg;
print "$_\n";
}
vagy
perl -ne 's/([\xC2\xC3])([\x80-\xBF])/chr(ord($1)<<6&0xC0|ord($2)&0x3F)/eg; print $_' file1 file2 ...
while (<INP>) {
chomp;
s/([\x80-\xFF])/chr(0xC0|ord($1)>>6).chr(0x80|ord($1)&0x3F)/eg;
print "$_\n";
}
- Konverzió kis/nagybetű megtartásával
sub preserve_case($$) {
my ($old, $new) = @_;
my $mask = uc $old ^ $old; # a nagybetűs kifejezést bitenként kizáró VAGYolja az eredeti kifejezéssel
uc $new | $mask . # az előző maszkot VAGYolja az új kifejezéssel
substr($mask, -1) x (length($new) - length($old)) # a mask utolsó karaktere szerint alkalmazza tovább a kis/nagybetűt
}
$a = "this is a TEsT case";
$a =~ s/(test)/preserve_case($1, "success")/egi;
print "$a\n";
eredménye:
this is a SUcCESS case
- URL címekben levő speciális karakterek
$url =~ s/([^a-zA-Z0-9])/sprintf('%%%02x',ord($1))/ge;
print "$i: $_" if /^\# START/ ... /^\# END/; # kinyomtat mindent a sor eleji #START és #END sorok között.
#!/usr/bin/perl
while (<>) {
print "header: $_" if 1 ... /^$/; # az első sor és első üres sor közötti rész
print "body: $_" if /^$/ ... eof(); # az első üres sor és állomány vége közötti rész
}
use LWP::Simple;
$url="http://elmfiz.elte.hu/fizinf/OpRendszerek/Perl.html";
$content = get $url; # a teljes HTML tartalmat betölti a content skaláris változóba
vagy
use IO::Socket;
unless (@ARGV > 1) {die "használat: $0 távoli_gépnév dokumentum ...";}
$host = shift(@ARGV);
foreach $document (@ARGV) {
$tavoli = IO::Socket::INET->new( Proto => "tcp",
PeerAddr => $host,
PeerPort => "http(80)",
);
unless ($tavoli) {die "nem tudtam csatlakozni a http démonhoz a $host gépen!";}
$tavoli->autoflush(1);
print $tavoli "GET $document HTTP/1.0\n\n";
while (<$tavoli>) {print}
close $tavoli;
}
vagy még általánosabban, interaktív párbeszéd a túloldali géppel:
use strict;
use IO::Socket;
my ($host, $port, $child, $handle, $sor);
unless (@ARGV == 2) {die "használat: $0 távoli_gépnév port ...";}
($host,$port)=@ARGV;
# tcp kapcsolat létrehozása
$handle = IO::Socket::INET->new( Proto => "tcp",
PeerAddr => $host,
PeerPort => $port,
)
or die "nem tudtam csatlakozni a $port portra a $host gépen: $!";
$handle->autoflush(1); # bufferelés kikerülése
print STDERR "[Csatlakozás a $host:$port-ra sikeres]\n";
# A program elágaztatása szülő és gyermek eljárásra:
die "nem sikerült a fork: $!" unless defined($child = fork());
# A szülő kapja a gyermek eljárás azonosítóját, a gyermek 0-t kap
if ($child) {
while (defined($sor = <$handle>)) {
print STDOUT $sor;
}
kill("TERM", $child); # SIGTERM küldése a gyermeknek
} else { # gyermek eljárás
while (defined($sor = <STDIN>)) {
print $handle $sor;
}
}
- Nemzeti karakterek
használata
use locale;
$ENV{"LC_ALL"}="hu_HU";