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";