Az unáris operátorok általában skalár környezetet nyújtanak az argumentumuknak, míg a lista operátorok skalár vagy lista környezetet nyújtanak. Ha mind a kettőt nyújtanak, akkor a skalár argumentumok mindig megelőzik a lista argumentumot, mivel mindig csak egy lista argumentum lehet. Például a splice függvény három skalár és egy lista argumentummal dolgozik.
A következő szintaxis leírásban azok a helyek, ahol a lista operátorok lista környezetet nyújtanak az argumentumaik számára LIST kulcsszóval esznek jelölve. Az ilyen listák tartalmazhatnak skalár argumentumokat vesszőkkel elválasztva, és listákat, amelyeket a Perl egyszerűen befűz a listába minden egyes elemükkel, egyre hosszabb listát előállítva. A LIST minden eleme vesszővel van elválasztva.
Bármelyik függvény, amelyet itt felsorolunk használható az argumentumait bezáró zárójellel,
vagy anélkül. (A szintakszis leírásban nem használunk zárójeleket.)
Ha használunk zárójeleket, akkor a nagyon egyszerű szabály szerint: ha függvénynek látszik,
akkor függvény és a precedencia nem számít. Egyéb esetekben unáris, vagy lista operátor és
az operátor precedenciák számítanak. A közök (szóköz, tab, újsor) a függvény neve és a paraméterek
körüli nyitózárójel között nem számít, ezért néha igencsak érdemes óvatosnak lenni:
print 1+2+3; # eredmény 6.
print(1+2) + 3; # eredmény 3.
print (1+2)+3; # szintén 3!
print +(1+2)+3; # eredmény 6.
print ((1+2)+3); # eredmény 6.
és a kimenet:
63366
Ha a Perl értelmezőt a -w opcióval futtatod, akkor ezekre a dolgokra figyelmeztet.
Azon függvények esetében, amelyek skalár és lista környezetben is használhatóak ha olyan hiba történik, amelyik miatt a program futásának nem kell megszakadnia nem definiált érték undef illetve nulla hosszúságú lista a visszatérési érték.
A következő szabály örökérvényű:
* - sub a Perl4 változatában kulcsszó volt, de a Perl5-ben operátor, amely kifejezésekben használható.
-r | a fájl olvasható az aktuális felhasználó által. (effective uid,gid) |
-w | a fájl írható az aktuális felhasználó által. (effective uid,gid) |
-x | a fájl végrehajtható az aktuális felhasználó által. (effective uid,gid) |
-o | a fájl az aktuális felhasználó tulajdona. (effective uid,gid) |
-R | a fájl olvasható a valódi felhasználó által. (real uid,gid). |
-W | a fájl írható az aktuális felhasználó által. (real uid,gid). |
-X | a fájl végrehajtható az aktuális felhasználó által (real uid,gid). |
-O | a fájl az aktuális felhasználó tulajdona. (real uid,gid) |
-e | a fájl létezik |
-z | a fájl nulla hosszú |
-s | a fájl nem nulla hosszú. Visszatérési érték a bájtok száma. |
-f | a fájl egyszerű fájl. |
-d | a fájl könyvtár |
-l | a fájl szimbólikus link. |
-p | a fájl egy megnevezett csatorna |
-S | a fájl egy socket. |
-b | a fájl block special fájl. |
-c | a fájl karakter speciális fájl. |
-t | a fájlkezelő egy tty-hoz (terminál) nyitott |
-u | a fájl setuid bitje be val állítva |
-g | a fájl setgid bitje be van állítva |
-k | a fájl sticky bitje be van állítva |
-T | a fájl szöveges fájl. |
-B | a fájl bináris (-T ellentéte). |
-M | a fájl kora napokban a Perl script indulásakor. |
-A | ugyanez, de a legutolsó hozzáférési időt figyelembe véve |
-C | ugyanez de inode változási időre |
A fájlhozzáférési operátorok, mint a -r, -R, -w, -W, -x és -X kizárólag csak a hozzáférési engedélyeket vizsgálják, ezen kívül még igen sok oka lehet annak, ha a program nem tudja például írni az egyik fájlt (például betelt a diszk). Ugyanakkor a superuser számára a -r, -R, -w és -W mindig 1-et ad vissza értékként, -x és -X 1-et ad vissza értékként ha bármelyik végrehajtási bit be van billentve. Így azok a programok, amelyeket a superuser futtat a stat függvényt kell, hogy használják, hogy a fájlok valódi módját megkapják, vagy a felhasználói azonosítót (uid) kell erre az időre átállítani.
Példa:
while (<>) {
chop;
next unless -f $_; # ignore specials
...
}
Megjegyzendő, hogy -s/a/b/ nem egy string csere mínusz egyszerese, hanem fájl méretre
való hivatkozás, osztva a-val és b-vel. Ugyanakkor -exp $foo
úgy működik, ahogy várjuk, mert csak az egybetűs operátorokat kezeli a Perl fájl tesztként.
A -T és -B kapcsolók a következőképpen működnek. A fájl első blokkját vizsgálja meg a rendszer, és keres bűvös kontrol kódokat, illetve olyan karaktereket, amelyeknek a legfelső bitje 1. Ha több mint 30% ilyen karaktert talál, akkor a fájl -B különben -T. Bármilyen fájl, amelyik nulla értékű karaktert tartalmaz az első blokkban bináris fájl. Ha ezen kapcsolókat fájlkezelőkre alkalmazzuk, akkor a beolvasott puffert vizsgálja meg a rendszer az első blokk helyett. Mind a két kapcsoló igaz értéket ad vissza nulla fájlon, illetve ha olyan fájlkezelővel hívják meg, amely EOF-on áll.
Mivel a -T és -B opciókhoz a fájl olvasása szükséges, azért érdemes a fájlt először a -f operátorral megvizsgálni, mint a next unless -f $file && -T $file.
Ha bármelyik fájl vizsgálat, beleértve a
stat
és
lstat
operátorokat is fájlkezelő, vagy fájlnév helyett magában álló aláhúzás karaktert kap
argumentumként, akkor az utolsó megvizsgált fájlra adja az eredményt. Ezzel egy
rendszerhívást megspórol a rendszer. (Kivéve a -t kapcsolót, és az is megjegyzendő,
hogy a
lstat
és -l a szimólikus link és nem a valódi fájl adatait hagyja a stat struktúrában.
Például:
print "Can do.\n" if -r $a || -w _ || -x _;
stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;
print "Setuid\n" if -u _;
print "Setgid\n" if -g _;
print "Sticky\n" if -k _;
print "Text\n" if -T _;
print "Binary\n" if -B _;
Ennél nagyobb pontosságú időállításhoz a Perl syscall felületét lehet használni a setitimer(2) rendszerfüggvényhez, ha a rendszer ezt támogatja, vagy a select függvényt. Nem ajánlott az alarm és sleep hívások keverése.
Gyakorlatilag a UNIX kivételével minden rendszeren szükséges ennek a függvénynek a megfelelő használata.
Ha FILEHANDLE egy kifejezés, akkor ennek az értékét használja a rendszer, mint a fájlkezelő nevét.
Mindig a kétargumentumos változatot használd, ha olyan konstruktor eljárást írsz, amelyik örökölhető.
($package, $filename, $line) = caller;
Ha EXPRESSION is meg van adva, akkor néhány olyan extra információt is visszaad, amelyet
a debugger használ. EXPRESSION értéke mondja meg, hogy hány hívási keretet menjen vissza az
aktuálishoz viszonyítva.
($package, $filename, $line,
$subroutine, $hasargs, $wantargs) = caller($i);
Amikor a DB csomagon belül kerül meghívásra még további részletes információ is kiértékelődik, nevezetesen a @DB::args listába bekerül a szubrutin argumentumainak a listája.
$cnt = chmod 0755, 'foo', 'bar'; chmod 0755, @executables;
open(F,"<input.txt"); @q = <>; close F; chomp @q;
A chomp függvény bármire használható, ami balérték, így akár egy értékadásra is.
chomp($cwd = `pwd`);
chomp($answer = <STDIN>);
while (<>) { chop; # avoid \n on last field @array = split(/:/); ... }Mindenre alkalmazható a függvény, ami balérték, így értékadáshoz is.
chop($cwd = `pwd`); chop($answer = <STDIN>);Ha argumentumként lista van megadva, akkor a lista minden egyes elemére alkalmazza az utolsó karakter levágást, de csak a legutolsó levágott karaktert adja vissza.
A chop a füzér utolsó karakterét adja vissza. A többi karakter visszaadása, azaz minden karakter kivéve az utolsót a substr($string, 0, -1) függvénnyel lehetséges.
A legtöbb rendszeren ez a parancs csak superuser jogosultsággal hajtható végre, de elképzelhető, hogy mások számára is engedélyezett a parancs végrehajtása olyan esetben, amikor a fájl tulajdonosa csak a csoporthoz tartozást akarja kicserélni valamely másodlagos csoportra.
Annyi különbség van, hogy az explicit módon végrehajtott fájl lezárás lenullázza a sorszámlálót $., míg az open által végrehajtott implicit lezárás nem.
Hasonlóan, ha egy csőhöz rendelt fájlkezelőt explicit módon lezár a program, akkor a
várni fog a processz lefutására, és a $? változó értékét is beállítja a processz
befejezési értékére.
open(OUTPUT, '|sort >foo'); # cső a sort programhoz
... # nyomtatás a csőbe
close OUTPUT; # megvárja amíg a rendezés befejeződik
open(INPUT, 'foo'); # elkezdjük beolvasni az eredményt
(Persze ennél van hatékonyabb rendezési lehetőség is.)
A FILEHANDLE lehet egy kifejezés is, amelyik a fájlkezelő nevét adja meg.
Ez a függvény használható a password fájl ellenőrzésére, például azért, hogy a rendszergazda ellenőrizze, hogy a felhasználók kellően bonyolult jelszót választottak.
Egy kódrészlet, amelyik ellenőrzi, hogy aki a kódot futtatja tudja a saját UNIX
jelszavát:
$pwd = (getpwuid($<))[1];
$salt = substr($pwd, 0, 2);
system "stty -echo";
print "Password: ";
chop($word = <STDIN>);
print "\n";
system "stty echo";
if (crypt($word, $salt) ne $pwd) {
die "Sorry...\n";
} else {
print "ok\n";
}
Természetesen a kulcsszavunkat megadni ismeretleneknek rettentő butaság, még akkor is
ha ez az ismeretlen csupán egy program.
Megszünteti a kapcsolatot a DBM fájl és a hozzá rendelt tördelőtábla között.
Ez a függvény hozzárendeli egy dbm(3), ndbm(3), sdbm(3), gdbm(), vagy Berkeley DB fájlt egy tördelőtáblához. ASSOC a tördelőtábla neve. Ellentétben a szokásos open függvénnyel az első argumentum nem fájl kezelő, hanem asszociatív tömb, vagy másnéven tördelőtábla. A második argumentum a fájl neve kiterjesztés nélkül. Ha a fájl nem létezik, akkor a program létrehozza a fájlt a harmadik paraméterként megadott hozzáférési MODE beállításával. (Ez az umask függvénnyel állítható.)
Ha a rendszer csak a régebbi fajta DBM függvényeket támogatja, akkor egy program csak egy dbmopen utasítást hajthat végre. A Perl régebbi verzióiban, ha a rendszeren nem volt sem DBM sem pedig ndbm, a dbmopen hívása hibát generált. Jelenleg ebben az esetben sdbm(3) kerül használatra.
Ha a DBM fájlhoz csak hozzáférési joga van a programnak, akkor csak olvasni fogja tudni a tördelőtábla egyes elemeit, de értéket nem adhat nekik. Ha tesztelni akarod, hogy tudod-e írni a fájlt, akkor használhatók a fájl tesztek, illetve meg lehet próbálni értéket adni a tábla egy elemének egy eval blokkon belül, amely megfogja a hibát.
Megjegyzendő, hogy az olyan függvények, mint a keys vagy values igen nagy tömböket
adhatnak vissza amikor nagyméretű DBM fájlhoz rendelt tördelőtáblára alkalmazzák őket. Ehelyett inkább
a each függvényt kell használni.
# print out history file offsets
dbmopen(%HIST,'/usr/lib/news/history',0666);
while (($key,$val) = each %HIST) {
print $key, ' = ', unpack('L',$val), "\n";
}
dbmclose(%HIST);
A tördelőtáblák esetén ellenőrizhető, hogy a tördelő tábla megfelelő eleme definiált-e.
Előfordulhat, hogy a tördelőtábla eleme létezik, de értéke undef ezért annak ellenőrzése,
hogy a tördelőtábla eleme létezik-e precízebben vizsgálható a exists függvénnyel.
print if defined $switch{'D'};
print "$val\n" while defined($val = pop(@ary));
die "Can't readlink $sym: $!"
unless defined($value = readlink $sym);
eval '@foo = ()' if defined(@foo);
die "No XYZ package defined" unless defined %_XYZ;
sub foo { defined &$bar ? &$bar(@_) : die "No bar"; }
Az undef függvény tartozik ehhez a témához.
Megjegyzés:
Sokan használják a defined függvényt feleslegesen. Például a
"ab" =~ /a(.*)b/;
esetében a hasonlítás sikeres, és $1 értéke definiált, annak ellenére, hogy az értéke semmi,
azaz nulla hosszúságú füzér. Pontosan fogalmazva, nem az az igaz, hogy $1 semminek sem felel
meg a hasonlításban, hanem az, hogy $1 a semminek felel meg.
A következő programrészlet az %ARRAY tördelőtábla összes elemét törli:
foreach $key (keys %ARRAY) {
delete $ARRAY{$key};
}
(Bár gyorsabb lenne az undef használata.)
Az EXPRESSION kifejezés értéke bármi lehet feltéve, hogy az utolsó művelet efy tördelőtábla
indexelés, például:
delete $ref->[$x][$y]{$key};
eval kiértékelésen belül a die hatására az eval blokk nem értékelődik ki tovább, az értéke undef és az üzenet a $@ változóba kerül. Ezzel lehetőség nyílik arra, hogy die függvény kivételt okozzon.
Egyenrangú példák:
die "Can't cd to spool: $!\n" unless chdir '/usr/spool/news';
chdir '/usr/spool/news' or die "Can't cd to spool: $!\n"
Ha az EXPRESSION kifejezés végén nincs újsor karakter, akkor a program aktuális
sorszámlálója és a bemeneti rekord számláló is hozzáadódik füzérhez.
A következő két példa egyenértékű:
do 'stat.pl';
és
eval `cat stat.pl`;
kivéve, hogy az első megoldás hatékonyabb, érthetőbb, kevésbé rendszerfüggő, figyelembe veszi az aktuális program fájlnevet a hibajelzések számára, és végigkeresi az összes -I könyvtárak a fájl megtalálásához, ha a fájl nem található meg az aktuális könyvtárban. Abban viszont teljes egészében megegyezik a két megoldás, hogy mind a kettő minden egyes alkalommal beolvassa, és a Perl interpreter értelmezi a parancsokat valahányszor az utasítás végrehajtódik, így feltehetőleg nem akarod majd végrehajtani egy ciklus belsejében.
A könyvtári függvények beemelésére sokkal jobb módszer a use és require operátorok használata.
Példa:
#!/usr/bin/perl
require 'getopt.pl';
require 'stat.pl';
%days = (
'Sun' => 1,
'Mon' => 2,
'Tue' => 3,
'Wed' => 4,
'Thu' => 5,
'Fri' => 6,
'Sat' => 7,
);
dump QUICKSTART if $ARGV[0] eq '-d';
QUICKSTART:
Getopt('f');
while (($key,$value) = each %ENV) { print "$key=$value\n"; }Nézd még meg a keys és values függvényeket.
Megjegyzendő, hogy ez a függvény egy karaktert olvas a fájlból, majd az ungetc C függvénnyel visszarakja az értéket. Az eof használata terminál fájlon, vagy az abból való olvasás hatására a terminál féjl elvesztheti a fájlvégjelet.
Ha nem adunk meg argumentumot az eof függvénynek, akkor azt a fájlkezelőt használja
amelyet legutoljára használt olvasási utasítás. Az üres zárójelek () használata
azokra a peszeudo fájlokra vonatkozik, amelyeket a parancssorban adtunk meg, így az
eof() használható egy while(<>) ciklusban az utolsó fájl végének
ellenőrzésére. A eof(ARGV)-t kell használni ha minden egyes fájl végét tesztelni akarjuk.
Példák:
# lenullázza a sorszámozást minden új fájl előtt
while (<>) {
print "$.\t$_";
close(ARGV) if (eof); # Nem eof()
}
és
# mínuszjeleket szúr be az utolsó fájl utolsó sora elé
while (<>) {
if (eof()) {
print "--------------\n";
close(ARGV); # close vagy break; szükséges, ha a
# terminálrólolvasunk
}
print;
}
Gyakorlatilag soha nincs szükség Perl-ben az eof használatára, mert
a beolvasó függvények visszatérési értéke undef ha kifutnak a beolvasható értékekből.
Ha szintaktikus hiba van a programrészletben, futási hiba történik, vagy egy die utasítást hajt végre a program, akkor undef értéket ad vissza a függvény és $@ tartalmazza a hibaüzenetet. Ha nem történthiba, akkor $@ garantáltan nulla hosszúságú füzér. Ha az argumentumként megadott EXPRESSION nincs megadva, akkor a függvény $_-t használja. Az utolsó pontosvessző hiányozhat a kifejezésből.
Mivel a eval függvény elfogja az egyébként végzetes hibákat, még a szintaktikus hibákat is, ezért az eval függvény használható annak ellenőrzésére, hogy egyes rendszerfüggő eljárások működnek-e egy adott környezetben. Így például ellenőrizhető, hogy a socket vagy symlink függvények implementáltak-e. Az eval használható arra is, hogy a die függvénnyel kivételeket lehessen megvalósítani.
Ha a kód az egyes végrehajtások között nem változik, akkor az eval BLOCK használható
arra, hogy az egyes hibákat megfogja a rendszer anélkül, hogy minden egyes végrehajtáshoz a Perl
újrafordítaná a kódrészletet. A hibaüzenet, ha van, ebben az esetben is $@ változóba kerül.
Példák:
# nullával való osztásután tovább fut a program
eval { $answer = $a / $b; }; warn $@ if $@;
# ugyanaz, de kevésbé hatékony
eval '$answer = $a / $b'; warn $@ if $@;
# ez fordítás ideji hibát generál
eval { $answer = };
# ez viszont futási időben csak $@ értékét állítja be
eval '$answer ='; # sets $@
Az eval használatánál különösen oda kell figyelni arra, hogy mit is hajt végre a Perl
futtató. Például
eval $x; # 1. ESET
eval "$x"; # 2. ESET
eval '$x'; # 3. ESET
eval { $x }; # 4. ESET
eval "\$$x++" # 5. ESET
$$x++; # 6. ESET
Az első két változat egyenértékű, mind a kettő az $x változóban levő füzért hajtja végre, mint
Perl programrészletet, annak ellenére, hogy az idézőjelek a második esetben egy kicsit
félrevezetők, és a program olvasója egy kicsit megakad elgondolkodva azon, hogy vajon még mi
történik itt az idézőjelek miatt (semmi). A harmadik és negyedik eset hasonló módon azonos, a
végrehajtott kód $x, ami végső soron nem csinál semmit. Az ötödik eset az, amikor az idézőjelek
használatának igazából értelme van, kivéve azt, hogy ebben az esetben szimbolikus referenciát is lehet használni.
Ha több, mint egy argumentuma van a függvénynek, vagy, ha az argumentum egy tömb, amelynek több, mint egy eleme van, akkor a rendszer az execvp(3) rendszerhívást hajtja végre, a LIST argumentumokkal. Ha csak egy skalár argumentuma van a függvénynek, akkor ezt a rendszer shell metakarakterek szempontjából ellenőrzi. Ha van ebben shell metakarakter, akkor az egész argumentumot átadja a rendszer a /bin/sh -c paranccsal a rendszernek. Ha nincsenek metakarakterek, akkor az argumentum szavakra lesz bontva, és az így keletkezett szó lista kerül direkt módon az execvp() rendszerhívásba.
Sem az exec, sem pedig a system függvények nem söprik ki a kimeneti puffereket, ezért érdemes $| változót beállítani, hogy ne vesszen el kimenet.
Példák:
exec '/bin/echo', 'Your arguments are: ', @ARGV;
exec "sort $outfile | uniq";
Ha hazudni akarsz a végrehajtandó programnak a nevét illetően, akkor a
lista elé indirekt objektumként, vessző nélkül lehet beírni a végrehajtandó parancsot.
Ebben az esetben az argumentumokat minden esetben listaként értelmezi a Perl, még
abban az esetben is, ha csak egy skalár érték szerepel a listában.
Példák:
$sh = '/bin/csh';
exec $sh '-sh'; # nézzen ki úgy, mint egy login shell
vagy direktebb módon:
exec {'/bin/csh'} '-sh'; # nézzen ki úgy, mint egy login shell
Példa:
print "Exists\n" if exists $array{$key};
print "Defined\n" if defined $array{$key};
print "True\n" if $array{$key};
Egy elem lehet TRUE, ha definiált, és definiált, ha létezik, de a fordított állítás nem feltétlenül igaz.
A kifejezés tetszőlegesen bonyolult lehet, feltéve, hogy az utolsó művelet egy
tördelőtábla keresés, például
if (exists $ref->[$x][$y]{$key}) { ... }
Példa:
$ans = <STDIN>;
exit 0 if $ans =~ /^[Xx]/;
Hasonló függvény: die.
Az argumentumok kezelése éppen úgy történik, mint a ioctl függvénynél. Az fcntl minden olyan gépen, amelyen nincsen implementálva a fcntl rendszerfüggvény fatális hibát generál.
Példa:
use Fcntl;
fcntl($filehandle, F_GETLK, $packed_return_buffer);
Egyes rendszereken az flock nem működik hálózaton keresztüli fájlokra, ilyenkor a sokkal rendszerfüggőbb fcntl használandó.
Egy egyszerű példa, amely egy BSD rendszerben a mailbox-hoz fűz hozzá:
$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;
sub lock {
flock(MBOX,$LOCK_EX);
# és ha esetleg valaki írt a fájl végéhez
# amíg vártunk...
seek(MBOX, 0, 2);
}
sub unlock {
flock(MBOX,$LOCK_UN);
}
open(MBOX, ``>>/usr/spool/mail/<STRONG>$ENV</STRONG>{'USER'}'')
or die ``Can't open mailbox: $!'';
lock();
print MBOX $msg,"\n\n";
unlock();
Ha a fork függvényt úgy hívod meg, hogy nem vársz a gyermek processzre, akkor zombikat generálsz:
$SIG{CHLD} = sub { wait };
Egy mási dupla fork trükk:
unless ($pid = fork) {
unless (fork) {
exec "amit csak végre akarunk hajtani";
die "nincs exec";
# ... vagy ...
## (Perl kód jön ide)
exit 0;
}
exit 0;
}
waitpid($pid,0);
format Something = Test: @<<<<<<<< @||||| @>>>>> $str, $%, '$' . int($num) . $str = "widget"; $num = $cost/$quantity; $~ = 'Something'; write;
Tulajdonképpen amikor egy write függvényhívás történik a $^ tartalma íródik ki egy fájlba.
if ($BSD_STYLE) { system "stty cbreak </dev/tty >/dev/tty 2>&1"; } else { system "stty", '-icanon', 'eol', "\001"; } $key = getc(STDIN); if ($BSD_STYLE) { system "stty -cbreak </dev/tty >/dev/tty 2>&1"; } else { system "stty", 'icanon', 'eol', '^@'; # ascii null } print "\n";
$login = getlogin || (getpwuid($<))[0] || "Verhas";Ugyanakkor a getlogin függvény nem ajánlott autentikációs feladatokhoz, mert nem elegendően biztonságos.
use Socket; $hersockaddr = getpeername(SOCK); ($port, $iaddr) = unpack_sockaddr_in($hersockaddr); $herhostname = gethostbyaddr($iaddr, AF_INET); $herstraddr = inet_ntoa($iaddr);
($name,$passwd,$uid,$gid, $quota,$comment,$gcos,$dir,$shell) = getpw* ($name,$passwd,$gid,$members) = getgr* ($name,$aliases,$addrtype,$length,@addrs) = gethost* ($name,$aliases,$addrtype,$net) = getnet* ($name,$aliases,$proto) = getproto* ($name,$aliases,$port,$proto) = getserv*
Ha a megfelelő elem nem létezik, akkor nulla listát ad vissza a rendszer.
Skalár környezetben a nevet adja vissza a rendszer, kivéve, ha függvény éppenséggel név szerinti keresésre irányul. Ekkor éppen a másik dolgot adja vissza a függvény, bármi legyen is az a másik dolog.
Ha a megfelelő elem nem létezik, akkor undef értéket ad vissza a rendszer.
Például:
$uid = getpwnam
$name = getpwuid
$name = getpwent
$gid = getgrnam
$name = getgrgid
$name = getgrent
stb.
A $members érték amit a getgr* függvények visszadnak a csoporthoz tartozó felhasználók login neveit adják meg egy füzérben szóközzel elválasztva.
A gethost*() függvények, amennyiben a C rendszer támogatja a h_errno
változót ennek értékét a $? változóban adják vissza. A @addrs változó,
amelyet a sikeres hívás ad vissza a nyers címeket tartalmazzák, amelyeket a
a megfelelő rendszerfüggvény adott vissza. Az Internet tartományban minden ilyen
cím négy bájt hosszú és kicsomagolható egy
($a,$b,$c,$d) = unpack('C4',$addr[0]);
paranccsal.
use Socket; $mysockaddr = getsockname(SOCK); ($port, $myaddr) = unpack_sockaddr_in($mysockaddr);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);Az összes listaelem numerikus, és direkt módon a struct tm rekordból kerülnek ki. Másszavakkal ez azt jelenti, hogy $mon nulla és 11 között lesz, $wday nulla és 6 között.
Ha nincs EXPRESSION megadva, akkor gmtime(time()) kerül kiszámításra.
Gyakorlatilag bárhova el lehet ugrani a dinamikus kereteken belül, akár ciklusból vagy szubrutinból ki is. Ugyanakkor ezekre alkalmasabb valamely más konstrukció, például last vagy die.
A goto EXPRESSION azt várja, hogy a kifejezés értéke egy cimke legyen, amelyet a kifejezés kiértékelése után megkeres a Perl értelmező, és onnan folytatja a futást. Ez olyan kiszámított goto lehetőséget ad, mint amilyent egyesek FORTRAN-ban szokhattak meg, de nem ajánlott a használata.
A gotot &NAME forma meghívja a NAME szubrutint, de amikor az visszatér akkor nem a goto utasítás után folytatódik a futás, hanem ott ahol ahonnan a goto-t tartalmazó szubrutint meghívták. Más szavakkal ez a goto olyan, mint egy szubrutinhívás, amelyet rögtön követ egy return utasítás, azzal a különbséggel, hogy a hívott szubrutin ebben az esetben más vermet, és más hívótlát (caller).
Ezt az utasítást általában a modulok AUTOLOAD szubrutinjai használják, amelyek futási időben, akkor töltenek be egyes szubrutinokat, amikor azokra a hivatkozás történik, majd úgy hívja meg azokat, mintha rögtön azokat hívta volna meg a program (kivéve, hogy minden módosítás, amely a @_ változón történik a hívott félnél megmarad). A goto után a még a caller függvény sem tudja megmondani, hogy nem ez a szubrutin volt elsőként meghívva.
@foo = grep(!/^#/, @bar); # kitöröljük a megjegyzéseket # ekvivalens módon @foo = grep {!/^#/} @bar; # ugyanezt csinálja
Mivel $_ referenciaként kerül beállításra, ezért használható arra, hogy a lista egyes elemeit módosítsa a grep függvény, de ez igen bizarr eredményeket adhat abban az esetben, amikor a LIST lista nem egy névvel hivatkozott tömb.
Ha EXPRESSION nincs megadva, akkor $_ értékét használja a függvény.
Ha a füzér nem található meg, akkor visszatérési érték -1, pontosabban fogalmazva $[-1.
require "ioctl.ph"; # probably in /usr/local/lib/perl/ioctl.phsorral be kell emelni a függvény definícióját. Ha ez a fájl nem létezik az adott rendszeren, akkor nem marad más, mint a megfelelő C fejléc fájlok alapján előállítani, de ez nem triviális.
SCALAR értékét fogja a függvény írni, illetve olvasni a FUNCTION függvénynek megfelelően. Ha SCALAR füzér, akkor a rendszerfüggvény a füzérre mutató mutatót ad át, míg ha értéke numerikus, akkor magát a numerikus értéket. Hogy biztos legyen, hog egy érték numerikus előtte adjunk hozzá nullát.
A pack és unpack függvények nagyon hasznosak lehetnek az ioctl függvény által kezelt struktúrák manipulálásához.
A következő példa a DEL karaktert állítja törlő karakterré:
require 'ioctl.ph';
$getp = &TIOCGETP;
die "NO TIOCGETP" if $@ || !$getp;
$sgttyb_t = "ccccs"; # 4 chars and a short
if (ioctl(STDIN,$getp,$sgttyb)) {
@ary = unpack($sgttyb_t,$sgttyb);
$ary[2] = 127;
$sgttyb = pack($sgttyb_t,@ary);
ioctl(STDIN,&TIOCSETP,$sgttyb)
|| die "Can't ioctl: $!";
}
Az ioctl és fcntl függvények visszatérési értéke
a következő:
az operációs rendszer a Perl visszatérési értéke visszatérési értéke -1 undef 0 füzér "0 de TRUE" bármi más szám maga a szám
Így a Perl függvény visszatérési értéke TRUE siker esetén, és FALSE hiba esetén,
mégis lehetőség van megnézni, hogy az operációs rendszer milyen értéket adott vissza.
($retval = ioctl(...)) || ($retval = -1);
printf "System returned %d\n", $retval;
print join('|' , (1,2,3,5,6,7,9,"kurtavas"));kimenete
1|2|3|5|6|7|9|kurtavasAz ellentétes hatású függvény, amely egy füzért szétbont listává a split.
Egy újabb példa a környezeti változók kiírására:
@keys = keys %ENV;
@values = values %ENV;
while ($#keys >= 0) {
print pop(@keys), '=', pop(@values), "\n";
}
és a környezeti változók azon a gépen, ahol e dokumentum HTML-re fordítása történt:
SYSTEMDRIVE=E:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.JS
OS2LIBPATH=E:\WINNT4\system32\os2\dll;
PROCESSOR_LEVEL=5
LIB=D:\Program Files\Mts\Lib
USERDOMAIN=DECINT
LOGONSERVER=\\CELEBRIS
HOMEPATH=\
TEMP=E:\TEMP
TMP=E:\TEMP
COMPUTERNAME=CELEBRIS
USERPROFILE=E:\WINNT4\Profiles\verhas
NUMBER_OF_PROCESSORS=1
PROCESSOR_REVISION=0205
PATH=C:\Perl5\bin;E:\WINNT4\system32;E:\WINNT4;;E:\MSSQL\BINN;;D:\Program Files\Mts;C:\DOS
WINDIR=E:\WINNT4
COMSPEC=E:\WINNT4\system32\cmd.exe
SYSTEMROOT=E:\WINNT4
INCLUDE=D:\Program Files\Mts\Include
HOMEDRIVE=E:
OS=Windows_NT
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 5 Model 2 Stepping 5, GenuineIntel
PROMPT=$P$G
USERNAME=verhas
$cnt = kill 1, $child1, $child2; kill 9, @goners;A shell-lel ellentétben, Perl-ben ha a jel értéke negatív, akkor processz csoportoknak küldi a kill a jelet. (A System V rendszereken is így van, az azonban nem hordozható, Perl-ben minden rendszeren így van, ahol a kill függvény implementált.) Ez azt jelenti, hogy általában pozitív értékeket kell használni. Használhatók a jelek nevei aposztrófok között is.
A program futása a parancs végrehajtásának hatására a ciklus
utáni utasításon folytatódik. continue blokk nem hajtódik végre.
$i = 7;
CIKLI:
while(1){
$j = 1;
while(1){
last if $j == 3 && $i < 9 ;
last CIKLI if $j == 3;
print $i,$j++ ;
}
$i++;
}
és a kimenete:
717281829192
A local által adott lokalitás futási idejű, és nem grammatikai. A grammatikai lokalitást a my utasítás adja.
Részletes leírás található a szbrutinokról szóló fejezetben.
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);Az összes listaelem numerikus, és direkt módon a struct tm rekordból kerülnek ki. Másszavakkal ez azt jelenti, hogy $mon nulla és 11 között lesz, $wday nulla és 6 között.
Ha nincs EXPRESSION megadva, akkor gmtime(time()) kerül kiszámításra.
Skalár környezetben füzérként írja ki az időt a ctime(3) rendszerhívásnak
megfelelően.
$a =localtime;
print $a;
Mon Jul 6 09:57:29 1998
@chars = map(chr, @nums);számok listáját konvertálja a megfelelő karakterekké.
%hash = map { getkey($_) => $_ } @array; ugyanaz, mint %hash = (); foreach $_ (@array) { $hash{getkey($_)} = $_; }
Részletes leírás található a szbrutinokról szóló fejezetben.
Ha a ciklushoz van continue blokk, akkor az ebben található utasítások végrehajtónak a next hatására, mielőtt a ciklus újraindulna.
Ha nincs megadva LABEL címke, akkor az utasítás a legbelső ciklusra vonatkozik.
$val = oct($val) if $val =~ /^0/;Ha EXPRESSION nincs megadva, akkor $_-t használja a rendszer.
Ha a fájlnév > karakterrel kezdődik, akkor írásra nyitja meg. Ha a fájlnév kezdete >> akkor hozzáírásra nyitja meg a fájlt (írásra a végére pozícionálva, így hozzáír a fájlhoz).
Egy + jel kerülhet a < vagy > jel elé a mind írásra, mind pedig olvasásra való megnyitáshoz. Általában a +< a szokásos írás/olvasás megnyitási forma, mivel a +> a fájlt először törli. Ezek megfelelnek a fopen(3) rendszerhívás 'r', 'r+', 'w', 'w+', 'a', és 'a+' módjainak.
Ha a fájlnév egy | karakterrel kezdődik, akkor a fájlnevet a rendszer mint parancsot értelmezi amelynek bemenete a cső, ha pedig az utolsó karakter, akkor olyan parancsként értelmezi a rendszer amelynek kimenetéből olvasunk.
Olyan open() parancsot nem lehet kiadni, amelyikbe írunk is és olvasunk is belőle.
- megnyitása a szabványos bemenet megnyitását jelenti, és >- megnyitása a szabványos kimenet.
Siker esetén a függvény visszatérési értéke nem nulla, hiba esetén undef. Ha a fájl történetesen egy cső, akkor a visszatérési érték az alprocessz PID-je.
Ha olyan rendszeren használod a Perl-t, amelyik különbséget tesz bináris és text fájlok között, akkor érdemes használni a binmode függvényt. A lényegi különbség a text fájlok sorvégjelölésében van.
$ARTICLE = 100;
open ARTICLE or die "Can't find article $ARTICLE: $!\n";
while (<ARTICLE>) {...
open(LOG, '>>/usr/spool/news/twitlog'); # (log is reserved)
open(DBASE, '+<dbase.mine'); # open for update
open(ARTICLE, "caesar <$article |"); # decrypt article
open(EXTRACT, "|sort >/tmp/Tmp$$"); # $$ is our process id
# feldolgozzuk a fájlokat, és minden include fájlt
foreach $file (@ARGV) {
process($file, 'fh00');
}
sub process {
local($filename, $input) = @_;
$input++; #ez füzér növelés!!
unless (open($input, $filename)) {
print STDERR "Can't open $filename: $!\n";
return;
}
while (<$input>) { # note use of indirection
if (/^#include "(.*)"/) {
process($1, $input);
next;
}
... # bármilyen kód
}
}
A Bourne shell hagyományainak megfelelően ha a fájlnév >& karakterekkel kezdődik, akkor a füzér további része, mint a fájlkezelő neve értelmeződik, és ez lesz megduplázva és megnyitva. Az & karakter használható >, >>, <, +>, +>> és +< után. A módnak ugyanannak kell lenni, mint az eredeti fájlnál.
Itt egy rövid script, amely elmenti, átirányítja, és visszaállítja az STDOUT és STDERR-t:
#!/usr/bin/perl
open(SAVEOUT, ">&STDOUT");
open(SAVEERR, ">&STDERR");
open(STDOUT, ">foo.out") || die "Can't redirect stdout";
open(STDERR, ">&STDOUT") || die "Can't dup stdout";
select(STDERR); $| = 1; # make unbuffered
select(STDOUT); $| = 1; # make unbuffered
print STDOUT "stdout 1\n"; # this works for
print STDERR "stderr 1\n"; # subprocesses too
close(STDOUT);
close(STDERR);
open(STDOUT, ">&SAVEOUT");
open(STDERR, ">&SAVEERR");
print STDOUT "stdout 2\n";
print STDERR "stderr 2\n";
Ha a fájlnév <&= karakterekkel kezdődik, akkor a Perl a C nyelv fdopen függvényének megfelelően működik.
Ha egy csövet (pipe) nyitunk meg a - fájlnévre, akár |- akár pedig -| formában, akkor implicit módon egy fork hajtódik végre. Az open visszatérési értéke ebben az esetben a gyermek processz PID-je az apában és 0 a gyerekben. (Ilyenkor az open értéke helyett a defined függvénnyel kell megvizsgálni, hogy sikeres volt-e a megnyitás.) Az apában a fájlkezelő normálisan lesz megnyitva, és az írás/olvasás a gyermek processz felé halad/onnan jön. A gyerekben a fájlkezelő nem lesz megnyitva, az írás és olvasás a szabványos bemeneten és kimeneten kell, hogy történjen.
A close meghívása bármely csőre a gyermek processz végére való várakozást jelenti és a visszatérési érték $? változóba kerül.
Minden olyan operációs esetén, amelyik fork-ot hajt végre, a kiürítetlen pufferek kiürítetlenek maradnak, ezért ezekre a $| értékét 1-re kell állítani.
A FileHandle csomag használatával lehetőség van olyan fájlkezelő nevek kialakítására,
amelyek ugyanolyan környezetben használhatók, mint a rájuk hivatkozó változók, és automatikusan
bezárja őket a rendszer, amikor minden hivatkozás megszűnik a fájlra:
use FileHandle;
...
sub read_myfile_munged {
my $ALL = shift;
my $handle = new FileHandle;
open($handle, "myfile") or die "myfile: $!";
$first = <$handle>
or return (); # automatikusan bezárja itt
mung $first or die "mung failed"; # vagy itt
return $first, <$handle> if $ALL; # vagy itt
$first; # vagy itt
}
A fájlnévből, amelyet az open megkap a bevezető és a lezáró szóközöket kitörli.
Emiatt, ha olyan fájlt akarsz megnyitni, amely bevezető, vagy lezáró szóközöket
tartalmaz, ezeket meg kell védeni. Ennek egy lehetséges módja:
$file =~ s#^(\s)#./$1#;
open(FOO, "< $file\0");
Ha igazi C open-t szeretnél, akkor a sysopen függvényt kell használni. Ez egy másik lehetőség
a fájlnév teljes megvédésére, például
use FileHandle;
sysopen(HANDLE, $path, O_RDWR|O_CREAT|O_EXCL, 0700)
or die "sysopen $path: $!";
HANDLE->autoflush(1);
HANDLE->print("stuff $$\n");
seek(HANDLE, 0, 0);
print "A fájl tartalma: ", <HANDLE>;
Érdemes még a seek függvényt is megtanulni ahhoz, hogy hogyan lehet az
olvasást, és az írást keverni.
Minden egyes betűt követhet egy szám, amely megadja, hányszor kell a betűt figyelembe venni. Minden típusnál, kivéve az ``a'', ``A'', ``b'', ``B'', ``h'', ``H'', és ``P'' típusokat a pack függvény ennyi argumentumot dolgoz fel az adott betűre a listából. A * mint ismétlési érték azt jelenti, hogy a lista maradék elemeit mind az adott típus szerint kell feldolgozni. Az ``a'' és ``A'' csak egy értéket vesz a listából, de a megadott szám hosszúságú füzért állít belőle elő nullákkal kiegészítve ha szükséges. Az unpack függvény használatakor az ``A'' leveszi a lezáró szóközöket és nullákat, de az ``a'' nem. Ennek megfelelően az ismétlési érték a ``b'' és ``B'' karaktereknél a bitek, a ``h'' és ``H'' karaktereknél a hexa digitek számát adja meg. A ``P'' esetén a szám a struktúra méretét adja meg, amelyre a mutató mutat. A valós számok (float és double) natív formában kerülnek tárolásra, mivel nincsen elfogadott szabvány, amely a hálózaton keresztüli adatcserét lehetővé tenné. Ez azt jelenti, hogy az egyik gépen összepakolt lebegőpontos számok nem feltétlenül kicsomagolhatók egy másikon, még akkor sem, ha mind a két gép IEEE lebegőpontos formátumot használ, mivel az IEEE formátum nem határozza meg a bájtsorrendet.
A Perl nyelv belül, mint a C mindig duplapontosságú számokat használ, ezért a simapontosságúra
való konverzió veszít a precizitásából. Emiatt például
unpack(``f'', pack(``f'', $foo) == $foo
nem feltétlenül igaz.
$foo = pack("cccc",65,66,67,68);
# foo eq "ABCD"
$foo = pack("c4",65,66,67,68);
# ugyanaz
$foo = pack("ccxxcc",65,66,67,68);
# foo eq "AB\0\0CD"
$foo = pack("s2",1,2);
# "\1\0\2\0" little-endian gépen
# "\0\1\0\2" big-endian gépen
$foo = pack("a4","abcd","x","y","z");
# "abcd"
$foo = pack("aaaa","abcd","x","y","z");
# "axyz"
$foo = pack("a14","abcdefg");
# "abcdefg\0\0\0\0\0\0\0"
sub bintodec {
unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}
Általánosan azt lehet mondani, hogy ugyanazt a TEMPLATE füzért lehet használni az unpack
függvényben is.
Tipikusan ez az az utasítás, amely elsőkét szerepel egy olyan fájlban, amelyet egy require vagy use függvénnyel használ valamely Perl program.
Egy ilyen csomagba több helyen is be lehet kapcsolódni, a package utasítás csak annyit mond a fordítónak, hogy mely névterületet használja a fordítás során a blokk végéig.
Más névterületen levő változókra, vagy fájlkezelőkre explicit névterület megadással lehet hivatkozni, a névterületet a változó neve elé kell írni két kettősponttal elválasztva: $csomag::változó. Ha a csomag neve nulla, akkor a main csomagot használja a Perl, azaz $::quty ugyanaz, mint $main::quty.
$tmp = $ARRAY[$#ARRAY--];utasításnak.
Ha a tömbben nincsen egyetlen elem sem, akkor a visszatérési érték undef. Ha nincs argumentum megadva, akkor az @ARGV tömböt használja a főprogramban, és a @_ tömböt szubrutinokban, éppen úgy, mint a shift.
Példa
# 11111
# 012345678901234
# | | | |
$s = 'bbb abbbabb bbb';
while( $s =~ m/bb/g ){
print pos($s),"\n";
}
amelynek kimenete
2
7
11
14
és
# 111111
# 0123456789012345
# || || | ||
$s = 'bbb abbbabb bbb';
while( $s =~ m/bb/g ){
print $i=pos($s),"\n";
pos($s) = --$i;
}
amelynek kimenete
2
3
7
8
11
14
15
Ha a FILEHANDLE nincs megadva, akkor a szabványos kimenetre nyomtat, illetve a legutoljára select függvénnyel kiválasztott csatornába. Ha a LIST lista is hiányzik, akkor $_ értékét írja ki. Mivel a print egy listát ír ki, ezért bármi, ami a print argumentumai között kiértékelődik lista környezetben értékelődik ki.
Oda kell figyelni arra is, hogy ha a listában az első argumentum valamiért nyitózárójellel kezdődik, akkor ezt a Perl a print függvény argumentumait körülzáró nyitó zárójelnek veszi és a záró zárójel utáni listaelemeket nem nyomtatja ki. Vagy egy + jelet kell a nyitózárójel elé tenni, vagy az összes argumentumot még egy zárójelpárba kell zárni.
Ha a FILEHANDLE neve egy tömb elemeként van megadva, vagy bármilyen más kifejezés értékeként, akkor
a kifejezést kapcsos zárójelek közé kell tenni.
print { $files[$i] } "stuff\n";
print { $OK ? STDOUT : STDERR } "stuff\n";
for $value (LIST) { $ARRAY[++$#ARRAY] = $value; }utasításnak, csak sokkal hatékonyabb.
Néhány Perl implementációban előfordulhat, hogy a rand függvény túl nagy, vagy túl kicsi értékeket ad vissza. Ennek oka, hogy a Perl értelmező fordításakor rosszul volt beállítva a RANDBITS C konstans. Ilyenkor az EXPRESSION kifejezést lehet az általában megfelelő kettő-hatvány értékkel megszorozni, de ezzel a program elveszti a hordozhatóságát. Sokkal jobb megoldás a megfelelő RANDBITS értékkel újrafordítani a programot.
Ha az így kapott értékeket, mint fájlneveket használod, akkor ne feledd el a
megfelelő könyvtár nevet eléjük illeszteni, vagy egy chdir parancsot kiadni.
opendir(DIR, $some_dir) || die "$some_dir nem nyitható meg: $!";
@dots = grep { /^\./ && -f "$some_dir/$_" } readdir(DIR);
closedir DIR;
if (ref($r) eq "HASH") { print "r is a reference to an associative array.\n"; } if (!ref ($r) { print "r is not a reference at all.\n"; }
Egyéb esetben azt követeli meg, hogy egy könyvtári fájl betöltődjön, ha még nem lett betöltve.
A fájl betöltése a do függvénnyel kerül betöltésre, amely az eval egy változata.
A require szemantikája hasonlít a következő Perl-ben megírt függvényre:
sub require {
local($filename) = @_;
return 1 if $INC{$filename};
local($realfilename,$result);
ITER: {
foreach $prefix (@INC) {
$realfilename = "$prefix/$filename";
if (-f $realfilename) {
$result = do $realfilename;
last ITER;
}
}
die "Can't find $filename in \@INC";
}
die $@ if $@;
die "$filename did not return true value" unless $result;
$INC{$filename} = $realfilename;
$result;
}
A fájl nem lesz kétszer betöltve azonos név alatt. A fájnak a kiértékelés során TRUE értéket kell
visszaadnia, ez jelzi azt, hogy az inicializáló kód sikeresen futott le, ezért szokás ezeket a
fájlokat egy lezáró '1;' utasítással befejezni.
Ha EXPRESSION egy meztelen szó, akkor a require feltételezi, hogy a könyvtári fájl kiterjesztése .pm és a névben a :: jeleket kicseréli / jelekre. Ennél sokkal hatékonyabbés funkcionálisabb könyvtárbetöltési lehetőség a use használata.
@q = (1,2,3,4); print reverse @q; print reverse 'alma'; $b = reverse 'alma'; print $b;és a kimenet (érdemes egy pillanatra elgondolkodni rajta)
4321almaamla
print reverse 'alma'; print scalar reverse 'alma';
Nincs ellentétes list operátor, mert általában nincsen rá szükség. Ha valamit lista környezetben kell kiértékelni, az vagy listakörnyezetben van úgyis, vagy használható a @{[ (kifejezés) ]} alak, amely esetén a kifejezés lista környezetben fog kiértékelődni.
Néhány rendszer megköveteli a seek meghívását egy fájlon belüli olvasási és írási műveletek között. Ilyenkor a
seek(TEST,0,1);utasítás használható a fájlmutató helyben hagyásához. Ez arra is jó, hogy ha fájl végére értünk, és egy másik processz írja a fájlt, akkor törli a fájlvége feltételt. Ellenkező esetben a Perl egy újabb <FILE> műveletnél nem próbál meg olvasni a fájlból, akkor sem ha közben valaki írt bele. Ellenben ha a seek függvényt meghívjuk, akkor újra próbálkozik.
Ha ez mégsem működne (végül is a Perl rendszer C-ben van megírva, és minden rendszeren a stdio
könyvtárat használja, és ez a működés ettől függ) akkor valami ehhez hasonlót kell
megpróbálni:
for (;;) {
for ($curpos = tell(FILE); $_ = <FILE>; $curpos = tell(FILE)) {
# itt csinálunk valamit és kiírunk a fájlba
}
sleep($for_a_while);
seek(FILE, $curpos, 0);
}
$oldfh = select(STDERR); $| = 1; select($oldfh);
$rin = $win = $ein = ''; vec($rin,fileno(STDIN),1) = 1; vec($win,fileno(STDOUT),1) = 1; $ein = $rin | $win;Ha sok fájlkezelőt egyszerre akarsz kiválasztani, akkor a következő szubrutin segíthet:
sub fhbits { local(@fhlist) = split(' ',$_[0]); local($bits); for (@fhlist) { vec($bits,fileno($_),1) = 1; } $bits; } $rin = fhbits('STDIN TTY SOCK');A szokásos forma:
($nfound,$timeleft) = select($rout=$rin, $wout=$win, $eout=$ein, $timeout);
vagy blokkolni, amíg valami rendelkezésre nem áll
$nfound = select($rout=$rin, $wout=$win, $eout=$ein, undef);
A legtöbb rendszer nem ad vissza semmit a $timeleft-ben, ezért a select hívása skaláris környezetben csak $nfound értéket ad vissza.
A bitmaszkok bármelyike lehet undef. Az időhatár (timeout) ha meg van adva, akkor másodpercben értendő, de lehet tört érték is. Nem minden implementáció képes a $timeleft kiszámítására. Ebben az esetben ezek a rendszerek a $timeleft változóban a megadott értéket adják vissza.
Egy 250 milli-másodperces várakozást a következőképpen lehet megvalósítani:
select(undef, undef, undef, 0.25);
FIGYELMEZTETÉS: Ne keverd a pufferelt i/o műveleteket a select függvény használatával. Ilyenkor a sysread függvényt kell használni.
pack(``sss'',$semnum, $semop, $semflag)függvénnyel. A szemafor operációk számát az OPSTRING hossza adja meg. Visszatérési értéke TRUE siker esetén, és FALSE ha hiba történt.
Mivel POSIX-ban a setgrp nem fogad el argumentumokat, ezért csak a setgrp 0,0 a hordozható kód.
Visszatérési érték TRUE siker esetén FALSE hiba esetén.
Általában nem lehet az alarm és sleep függvényeket vegyesen használni, mert a legtöbb rendszeren a sleep függvény az alarm függvény felhasználásával van implementálva.
Néhány öregebb rendszeren egy másodperccel kevesebbet alszik a program, mint a valóban megkívánt.
Ennél finomabban beállítható várakozásra a Perl syscall függvényét lehet használni a setitimer(2) felület eléréséhez, ha ez az adott rendszeren elérhető, vagy a select függvényt.
Feltehetőleg használni kell a use Socket parancsot a megfelelő definíciók betöltéséhez.
SUBNAME lehet egy skaláris változó, amely esetben a változó értéke adja meg a hasonlításokhoz használt szubrutin nevét. A SUBNAME helyén megadható egy BLOCK blokk, mint egy rövid, egyszerű szubrutin.
A hatékonyság kedvéért a szokásos szubrutinhívási eljárásokat kihagyja a rendszer, aminek a következő következményei vannak:
# lexikális rendezés @articles = sort @files; # ugyanaz, csak most expliciten meg van adva a hasonlító blokk @articles = sort {$a cmp $b} @files; # kisbetű/nagybetű most nem számít @articles = sort { uc($a) cmp uc($b)} @files; # és ugyanez fordított sorrendben @articles = sort {$b cmp $a} @files; # numerikusan növekvő sorrendbe @articles = sort {$a <=> $b} @files; # numerikusan csökkenő sorrendbe @articles = sort {$b <=> $a} @files; # expliciten megadott szubrutin névvel sub byage { $age{$a} <=> $age{$b}; # presuming integers } @sortedclass = sort byage @class; # az %age tördelőtábla kulcsai az értékek szerint # rendezve @eldest = sort { $age{$b} <=> $age{$a} } keys %age; sub backwards { $b cmp $a; } @harry = ('dog','cat','x','Cain','Abel'); @george = ('gone','chased','yz','Punished','Axed'); print sort @harry; # prints AbelCaincatdogx print sort backwards @harry; # prints xdogcatCainAbel print sort @george, 'to', @harry; # prints AbelAxedCainPunishedcatchaseddoggonetoxyz
A következő utasítások azonosak, (feltételezzük, hogy $[ értéke nulla):
push(@a,$x,$y) splice(@a,$#a+1,0,$x,$y)
pop(@a) splice(@a,-1)
shift(@a) splice(@a,0,1)
unshift(@a,$x,$y) splice(@a,0,0,$x,$y)
$a[$x] = $y splice(@a,$x,1,$y);
Ha nem listakörnyezetben szerepel, akkor a megtalált mezők számát adja vissza, amelyek belekerültek a @_ tömbbe. (Listakörnyezetben is rá lehet venni a split függvényt, hogy a @_ tömbbe helyezze el az elemeket azzal, hogy ?? jeleket használunk, mint reguláris kifejezés határolókat, de ekkor is a listaelemeket adja vissza a függvény. Ugyanakkor az implicit módon @_-ba történő vágás ellenjavallt.
Ha nincsen megadva EXPRESSION kifejezés, akkor $_ értékét darabolja fel a függvény. Ha a PATTERN reguláris kifejezés sincsen megadva, akkor a szóközök mentén vágja szét a füzért a függvény (a bevezető szóközök után). Ha LIMIT meg van adva és pozitív, akkor legfeljebb ennyi mezőre vágja szét a füzért. Ha LIMIT nincs megadva, akkor a keletkező lista végén lévő üres mezőket levágja a függvény. Ha a LIMIT negatív, akkor azt úgy kezeli a függvény, mintha tetszőlegesen nagy lenne a LIMIT.
Ha a PATTERN megfelel a null füzérnek, akkor a füzért minden egyes karakter között
elvágja, így például
print join(':', split(/ */, 'hi there'));
kimenete
h:i:t:h:e:r:e
A LIMIT megadásával részlegesen lehet felvágni füzéreket.
($login, $passwd, $remainder) = split(/:/, $_, 3);
Amikor egy listának adunk értéket a függvénnyel, akkor a Perl automatikusan a lista elemeinek száma plusz egy értéket ad meg LIMIT-ként, ezzel is csökkentve a felesleges műveleteket. Az előbbi példában LIMIT értéke alapértelmezés szerint négy lett volna.
Ha a PATTERN reguláris kifejezésen belül zárójeleket használunk, akkor minden egyes részfüzérre,
amely megfelel a bezárójelezett résznek egy újabb listaelem keletkezik, például:
print join(':',split(/([,-])/, "1-10,20", 3));
kimenete
1:-:10:,:20
A reguláris kifejezés PATTERN helyettesíthető egy változóval, amelyiknek az értéke tartalmazza a
reguláris kifejezést.
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);Nem minden mező támogatott minden fájlrendszerben. Az egyes mezők értelme:
(Az időpontok 1970. január 1 0:00 GMT óta eltelt másodpercekben vannak megadva, mint általában minden időpont a UNIX-os rendszerekben.)
Ha a stat-nak egy speciális fájlnevet, az aláhúzás karaktert adjuk meg akkor nem hívja meg a rendszerfüggvényt, hanem a legutolsó fájltesztelés, vagy stat eredményeit használja.
Egy időben csak egy ilyen vizsgálat lehet aktív. Egy második skalár megvizsgálásának hatására az elsőt elfelejti a rendszer.
Ha az értékadás során a LEN értékénél kevesebb karaktert teszünk az alfüzér helyére, akkor az eredményül kapott füzér rövidebb lesz, ha többet, akkor hosszabb lesz.
Példák:
$k = "Almás deres\n";
print substr($k,2,4);
print substr($k,-6);
print substr($k,6,-1);
print substr($k,-7,-2);
substr($k,0,5) = "\nRétes";
print $k;
és a kimenet:
más deres
deres dere
Rétes deres
require 'syscall.ph'; syscall(&SYS_write, fileno(STDOUT), "ki van ott?\n", 9);
A Perl maximum 14 argumentumot ad át a rendszernek, ami a gyakorlatban elegendő kell, hogy legyen.
A lehetséges bit értékek a MODE paraméter számára rendszerfüggők, és a szabványos Fcntl modulon keresztül érhetők el. Ugyanakkor hagyomány okok miatt néhány érték univerzális, így nulla csak olvasásra, egy csak írásra és kettő írásra, olvasásra nyitja meg a fájlt.
Ha a fájl nem létezik, akkor a rendszerhívás létrehozza (általában azért, mert a MODE tartalmazza az O_CREAT bitet), majd ezután a PERM engedélyezési értéket rendeli hozzá. Ha PERM hiányzik, akkor alapértelmezés szerint 0666 az értéke (vigyázat, ez oktális szám, nem sátánista jelkép) amely alapján mindenki olvashatja és írhatja a fájlt.
Az objektum, amelyet a tie függvény visszaad a new metódus által létrehozott, és visszaadott objektum.
Megjegyzendő, hogy az olyan függvények, mint a keys vagy values igen nagy
tömböket eredményezhetnek olyan tördelőtáblák esetén, amelyek nem memóriában vannak
tárolva, hanem a tie függvénnyel DBM fájlokhoz vannak rendelve. Ilyen esetben
sokkal inkább az each függvényt kell használni, amely egyenként veszi elő az egyes
elemeket.
use NDBM_File;
tie(%HIST, 'NDBM_File', '/usr/lib/news/history', 1, 0);
while (($key,$val) = each %HIST) {
print $key, ' = ', unpack('L',$val), "\n";
}
untie(%HIST);
Az osztály, amely egy tördelőtáblát hoz létre a következő metódusokat kell, hogy megvalósítsa:
Az osztály, amely közönséges tömböt valósít meg a következő metódusokat kell, hogy megvalósítsa:
Az osztály, amely skalárt valósít meg a következő metódusokat kell, hogy megvalósítsa:
Ellentétben a dbmopen függvénnyel a tie függvény nem olvas be semmilyen modult, ezt a programnak egy külön require vagy use függvénnyel kell megtennie, ha szükséges.
($user,$system,$cuser,$csystem) = times;
undef $foo; undef $bar{'blurfl'}; undef @ary; undef %assoc; undef &mysub; return (wantarray ? () : undef) if $they_blew_it;
Megjegyzés: az unlink nem töröl könyvtárakat, csak akkor ha superuser módban fut a processz, és a Perl a -U kapcsolóval lett elindítva. Azonban még ebben az esetben is gondokat okozhat a fájlrendszerben egy könyvtár fájlként való eltávolítása. Sokkal biztonságosabb módszer az rmdir használata.
A következő példaprogram a substr és ord függvényeket valósítja meg:
sub substr {
local($what,$where,$howmuch) = @_;
unpack("x$where a$howmuch", $what);
}
sub ord { unpack("c",$_[0]); }
Ezen túlmenően minden mezőjelölő karaktert megelőzhet egy %<xxx> jelölés,
amely esetben nem a mező értékét adja meg az unpack hanem annak xxx bites
ellenőrző összegét.
A következő példa a System V sum parancsát valósítja meg:
while (<>) {
$checksum += unpack("%16C*", $_);
}
$checksum %= 65536;
A következő példa hatékonyan számolja össze egy bitvektor bitjeit:
$setbits = unpack("%32b*", $selectmask);
A LIST lista egésze, egyszerre lesz a tömb elejére illesztve, így a sorrend a tömb elején ugyan az lesz, mint a listában. Ha nem ez a kívánatos, akkor a reverse függvénnyel lehet a LIST lista elemeinek sorrendjét megfordítani.
BEGIN { require Module; import Module LIST; }
utasításnak, kivéve, hogy a Module a use esetében fix szó kell, hogy legyen, nem lehet füzér kifejezés.
Ha az első argumentum nem modul név, hanem szám, akkor a Perl megvizsgálja, hogy a saját verziója eléri-e ezt az értéket, és ha nem, akkor egy hibajelzés után azonnal leáll. Ezzel lehet megkövetelni azt a Perl verziót, amely alatt a program hibásan hajtódna végre.
A use estében a modul beimportálása fordítási időben történik, ezt a fenti ekvivalens példában a BEGIN éri el. Az import nem egyéb, mint egy, a modulban definiált statikus szubrutin, amely általában neveket rak át az importáló csomag névterületére. A modul olyan módon implementálhatja saját import szubrutinját, ahogy csak akarja, de a legtöbb csomag csak egyszerűen örökli az Exporter csomagból.
Ha az importáló nem akarja, hogy a névterülete megváltozzon, akkor a
use Module ();
alakot kell használni, amely ekvivalens a
BEGIN { require Module; }formával.
Ha a VERSION szerepel a Modul és a LIST lista között, akkor a use hibát okoz, ha a csomagban a $VERSION változó értéke kisebb, mint VERSION.
Mivel ez a formátum megfelelően nyitott, ezért sok fordítási direktíva is ebben a formában van megvalósítva. A pillanatnyilag implementált direktívák:
use integer; use diagnostics; use sigtrap qw(SEGV BUS); use strict qw(subs vars refs); use subs qw(afunc blurfl);
Ezek a pszeudo modulok a pillanatnyi blokk környezetben fejtik ki a hatásukat ellentétben az igazi modulokkal, amelyek a névtartományt módosítják, és így a fájl végéig hatásosak.
Van egy no parancs, amely a use ellentéte, és amely ennek megfelelően nem az import, hanem az unimport szubrutint hívja meg.
#!/usr/bin/perl $now = time; utime $now, $now, @ARGV;
Az így kezelt vektorokkal a logikai bitenkénti |, & és
^ használhatók.
#!/usr/bin/perl
vec($v,3,8)=64;
print unpack("b*", $v),"\n";
vec($v,9,1)=1;
vec($v,11,1)=1;
print unpack("b*", $v),"\n";
vec($v,0,3)=255;
print unpack("b*", $v),"\n";
és a kimenet
00000000000000000000000000000010
00000000010100000000000000000010
11100000010100000000000000000010
return wantarray ? () : undef;
A lapteteje automatikusan kezelődik, ha nincs elegendő hely az oldalon a rekord számára, akkor egy lapdobást ír ki a fájlba, majd a lap teteje fejlécet, és utána az aktuális rekordot. Alapértelmezés szerint a fejléc a fájlkezelő neve, amelyhez a _TOP karaktereket adja hozzá a rendszer, de tetszőlegesen átállítható, csupán a $^ változóhoz kell a formátum nevét rendelni, miközben a fájlkezelő van kiválaszva a select függvénnyel. A lapon fennmaradó sorok száma a $- változóba kerül, amelynek nulla értéket adva lapdobást lehet elérni a következő kiírásnál.
Ha a FILEHANDLE nincs megadva, akkor a kiírás az aktuális kimeneti csatornába megy, amely alapértelmezés szerint STDOUT, de megváltoztatható a select függvénnyel. Ha a FILEHANDLE helyett egy kifejezés van megadva, akkor a kifejezés adja meg a fájlkezelő nevét.
Megjegyzés: a write NEM a read ellentéte.