SYNOPSIS
Teks PPP ini ditulis dengan
tujuan untuk membantu orang Indonesia yang baru belajar menggunakan
Perl. Latar belakang bahasa C akan sangat membantu, meskipun bukan
syarat mutlak, akan tetapi pengalaman pemrograman dalam
sekurang-kurangnya satu bahasa lain diperlukan. Sebagai bahan tutorial,
teks ini dirancang untuk digunakan bersama dengan perlop. Jika
dokumen tersebut dirasa sulit dibaca karena terlalu teknis, Appendix A
disediakan untuk membantu memahami sejumlah istilah teknis di sana.
Rencananya
teks ini akan disampaikan sebagai salah satu materi pada
Pelatihan/Tutorial Linux KPLI Jateng (Kelompok Pengguna Linux di
Indonesia area Jawa Tengah, http://jateng.linux.or.id/), tanggal: m#\d+/\d+/1999#, di STMIK Dian Nuswantoro, Semarang, Indonesia.
1. PENDAHULUAN
1.1 Apa Itu Perl?
Menurut
Larry Wall (http://www.wall.org/) -penciptanya- Perl adalah akronim
dari Practical Extraction and Report Language, atau Pathologically
Eclectic Rubbish Lister. Perl diciptakan dengan menggabungkan
unsur-unsur dari bahasa C, awk, Bourne shell script, dan program-program
seperti sed, grep.
Tidak seperti shell script, Perl tidak
bergantung pada program-program eksternal, sehingga lebih cepat. Perl
adalah setengah kompiler dan setengah interpreter. Jika kita menjalankan
sebuah skrip Perl, maka skrip tersebut sebenarnya dikompilasi terlebih
dahulu ke dalam bentuk menengah (pohon syntax) yang kemudian
diinterpretasikan oleh sistem run-time Perl. Dengan demikian, eksekusi
skrip Perl lebih cepat daripada skrip bahasa-bahasa yang murni
terinterpretasi (interpreted language) seperti Tcl. Lebih lanjut lagi juga muncul teknik-teknik untuk lebih mempercepat lagi waktu eksekusi skrip Perl. Tidak seperti produk-produk proprietary seperti Java yang tidak pernah lepas dari isu-isu ``politik bisnis'', pengguna Perl bisa dengan tenang dan nyaman menggunakan Perl pada platform favoritnya. Seperti Linux, Perl dapat diperoleh secara bebas, karena berlisensi publik GNU.
Oleh para pakar bahasa pemrograman, Perl digolongkan ke dalam VHLL (Very High Level Language). Satu perintah dalam Perl ekivalen dengan banyak perintah dalam bahasa tingkat tinggi, sehingga program-program yang ditulis dalam Perl sangat efisien dan ringkas.
Perl merupakan pilihan utama untuk tugas-tugas pengolahan teks, terutama dengan fasilitas regular expression-nya yang sangat canggih. Dengan mewabahnya internet, dengan sejumlah protokolnya yang berbasis teks (NVT ASCII), Perl menjadi pilihan utama untuk pemrograman internet, terutama CGI (Common Gateway Interface).
Semula Perl hanya dipakai untuk menulis skrip-skrip pendek, namun dalam perkembangannya, Larry menambahkan dukungan bagi pemrograman berorientasi objek, dan dimulailah era baru pemrograman Perl untuk aplikasi-aplikasi besar dan rumit.
1.2 Membuat dan Mengeksekusi Program Perl
Gunakan editor teks (vi, jstar, emacs, atau apapun kesukaan Anda) untuk mengedit program Perl, pada baris pertama cantumkan path ke interpreter perl:
#!/usr/bin/perlSimpanlah sebagai file, biasanya dengan ekstensi .pl (tapi ini tidak penting bagi interpreter perl), dan ubah permissionnya ke executable (misalkan chmod 755, atau chmod +x).
1.3 Dokumentasi Perl (perlpod)
Dokumentasi
biasanya ditulis dalam format pod (Plain Old Documentation), untuk
membacanya, gunakan perldoc. Misalkan untuk membaca perlfaq.pod,
jalankan:
$ perldoc perlfaqTersedia juga konverter dari pod ke format-format lain seperti ASCII Text, dan HTML. Sebagai contoh, untuk membuat HTML dari perlfaq1.pod:
$ pod2html --infile=perlfaq1.pod --outfile=perlfaq1.htmlSedangkan untuk membuat ASCII Text:
$ pod2text perlfaq1.pod > perlfaq1.txtUntuk menuliskan komentar (comment) pada source code, tuliskan setelah simbol #.
2. DATA
Untuk
menciptakan variabel, perlu ditentukan tipe data bagi variabel
tersebut. Tipe data yang paling mendasar adalah skalar. Sebuah skalar
dapat berupa numerik ataupun string. Tipe data lainnya adalah array dari
skalar, dan array asosiatif (associative array) dari skalar.
2.1 Skalar
Variabel skalar ditulis dengan simbol $. Contoh:
$title = "Programming Perl"; #skalar string
$num = 10; #skalar numerikPerhatikan quote (tanda kutip) pada skalar string. Ada tiga macam quote: double quote (seperti pada contoh di atas), single quote, dan back quote. Jika kita gunakan double quote, maka kita izinkan penggunakan control character dan interpolasi variabel pada string tersebut. Berikut ini adalah contoh-contoh control character:
\n newline (baris baru)
\r carriage return
\t tabInterpolasi variabel berarti bahwa sebuah variabel yang digunakan dalam sebuah string disubstitusi dengan nilai variabel tersebut. Sekarang cobalah contoh berikut:
#!/usr/bin/perl
$title = "Programming Perl";
$num = 10;
$kalimat = "Jumlah buku $title sebanyak $num.\n";
print $kalimat;Jika kita gunakan single-quote, maka pada string tersebut tidak berlaku control character dan interpolasi variabel. Cobalah jalankan kembali contoh di atas setelah mengganti double-quote pada $kalimat menjadi single-quote, dan perhatikan perbedaannya. Interpolasi variabel tidak berlaku untuk array asosiatif (hash). Back-quote melakukan substitusi command yang dijalankan pada shell. Cobalah berikut ini:
$tanggal = `date`;
print "Jumlah buku $title pada $tanggal sebanyak $num.\n";Cara lain untuk menuliskan quote adalah dengan menggunakan q (single-quote), qq (double-quote), dan qx (back-quote). Contoh:
$tanggal = qx[date]; #sama dengan back-quote
$title = q/Programming Perl/; #sama dengan single-quote
$other = qq#Learning Perl#; #sama dengan double-quote
2.2 Array
Variabel array ditulis dengan simbol @. Contoh:
@small_nums = (1..20);
@authors = ("Larry", "Randal", "Friedl");
@amounts = qw(7 4 6); #sama dengan ('7', '4', '6')Indeks elemen array dimulai dari 0. Contoh:
print $authors[0], "\n"; #mencetak Larry
print $authors[2], "\n"; #mencetak FriedlBasis 0 ini sebenarnya dapat diubah dengan cara mengubah nilai $[. Contoh:
$[ = 1; #more convenient to awk folks
print $authors[1], "\n"; #mencetak LarrySekalipun praktek demikian tidak dianjurkan.
Untuk mengetahui indeks dari elemen terakhir dari sebuah array, gunakan simbol $#. Contoh:
print 'Indeks elemen terakhir = ', $#authors, "\n";
- shift dan pop
shift mengambil elemen terkiri dari array, sedangkan pop mengambil elemen terkanan. Contoh:
· $leftmost = shift @authors; #mengambil Larry
· print join("\n", @authors); #mencetak Randal, Friedl
· $rightmost = pop @authors; #mengambil Friedl
- unshift dan push
unshift menambahkan elemen array dari sisi kiri, sedangkan push menambahkan elemen array dari sisi kanan. Contoh:
· unshift(@authors, "Larry");
· push(@authors, "Srinivasan");
· print join("\n", @authors); #mencetak Larry, Randal, Srinivasan
- join dan split
join membentuk sebuah skalar dari elemen-elemen sebuah array yang dipisahkan oleh delimiter yang kita tentukan. Contoh:
· $all_authors = join("\n", @authors);
membentuk $all_authors yang berisi elemen-elemen @authors
yang dipisahkan karakter newline. Sebaliknya, split membentuk array
dari sebuah skalar dengan cara memisahkan elemen- elemen berdasarkan
pola pencocokan tertentu. Contoh:
@original = split(/\n/, $all_authors);
Mengenai pola pencocokan, akan kita lihat nanti lebih jauh pada bagian Regular Expression.
- sort
melakukan sort berdasarkan nilai ASCII. Contoh:
· @scores = (68, 50, 30, 78, 5, 58);
· print join(' ', sort @scores), "\n";
2.3 Array Asosiatif
Array
Asosiatif pada perl diimplementasikan sebagai hash table, dan memiliki
struktur seperti array, kecuali pada indeksnya yang berupa string,
sedemikian rupa sehingga hash tersusun dari pasangan-pasangan key-value.
Variabel hash ditulis dengan simbol %. Contoh:
%booklist = ("Larry", "Camel", "Randal", "Llama", "Srinivasan", "Panther",);atau:
%booklist = ("Larry" => "Camel",
"Randal" => "Llama",
"Srinivasan" => "Panther",);
print $booklist{'Larry'}, "\n"; #mencetak Camel
- keys dan values
keys membentuk array yg berisi key dari sebuah hash. Contoh:
· for (sort keys(%booklist))
· {
· print 'The ', $booklist{$_}, " book is a dead hack by $_\n";
· }
akan menghasilkan output:
The Camel book is a dead hack by Larry
The Llama book is a dead hack by Randal
The Panther book is a dead hack by Srinivasan
Sebaliknya values membentuk array yg berisi value dari sebuah hash. Contoh: for (values(%booklist)) { print $_, ``\n'';}
- each
each membentuk array yang berisi pasangan key - value dari elemen berikutnya dari sebuah array asosiatif. Contoh:
· while (($author, $beast) = each(%booklist))
· {
· print $author, ' => ', $beast, "\n";
· }
- delete
menghapus elemen hash berdasarkan key-nya. Contoh:
· delete $booklist{'Randal'};
· menghapus pasangan key - value Randal - Llama dari hash %booklist.
2.4 Konteks
Operasi-operasi
yang dilakukan terhadap data sebenarnya dilakukan di dalam konteks
tertentu, artinya jika hasil yang diharapkan dari sebuah operasi
terhadap data atau operand tertentu adalah skalar, maka dikatakan bahwa
data atau operand tersebut dievaluasi dalam konteks skalar. Selain
konteks skalar, dikenal juga konteks array atau list, dan konteks
boolean.
@booklist = %booklist; #menciptakan array dari hash
$jumlah_elemen = @authors; #mengambil jumlah elemen arrayKonteks boolean terutama digunakan dalam mengevaluasi sebuah ekspresi. Nilai SALAH adalah null string (``''), 0, ``0'', atau undef. Variabel yang tidak terdefinisi bernilai undef. Kita akan lihat penerapan konteks boolean pada pembahasan mengenai struktur kendali.
2.5 Referensi dan Variabel Anonim
Referensi
mirip dengan pointer pada C. Kita dapat menciptakan referensi ke
variabel bernama, maupun ke variabel anonim (tak bernama). Untuk
menciptakan referensi ke variabel bernama, kita gunakan backslash di
depan variabel tersebut. Contoh:
$amount = 7;
@beasties = ("Camel", "Llama", "Panther");
%booklist = ("Larry", "Camel", "Randal", "Llama", "Srinivasan", "Panther",);
$amountref = \$amount; #ref ke skalar
$beastiesref = \@beasties; #ref ke array
$booklistref = \%booklist; #ref ke hash
print ref($amountref), "\n";
print ref($beastiesref), "\n";
print ref($booklistref), "\n";ref() mengambil tipe referensi, sehingga output contoh di atas adalah:
SCALAR
ARRAY
HASHUntuk menciptakan referensi ke array anonim, kita gunakan kurung persegi, dan untuk referensi ke hash anonim, kita gunakan kurung kurawal. Contoh:
$ref_to_scalar = \5;
$ref_to_arr = [1, 2, 3];
$ref_to_hash = {'satu' => 1, 'dua' => 2, 'tiga' => 3};
print ${$ref_to_scalar}, "\n";
for (@$ref_to_arr) {print $_, "\n";}
print 'Elemen ke-0: ', $$ref_to_arr[0], "\n";
print 'Elemen ke-2: ', ${$ref_to_arr}[2], "\n";
print 'Elemen ke-1: ', $ref_to_arr->[1], "\n"; #C style
for (sort keys(%$ref_to_hash)) {print $_, ': ', $$ref_to_hash{$_}, "\n";}Karena TMTOWTDI (There's More Than One Way To Do It), ada beberapa cara untuk mengakses elemen dari variabel anonim. Kita dapat menggunakan konteks yang sesuai dengan tipe referensinya. Misalkan karena $ref_to_scalar memiliki tipe referensi SCALAR, maka kita ambil nilai skalar anonim tersebut dengan cara menempatkannya di dalam konteks skalar: ${$ref_to_scalar}, atau lebih singkat: $$ref_to_scalar. Demikian juga untuk array dan hash anonim, kita dapat menempatkannya dalam konteks array dan hash, dan kemudian melakukan operasi array dan hash seperti biasa. Seperti pada contoh di atas kita melihat @$ref_to_arr, dan kemudian mengiterasi elemen-elemennya dengan for(). Namun ada cara lain yang lebih akrab bagi programmer C/C++, yaitu dengan operator panah, sehingga kita melihat juga $ref_to_arr->[0] untuk mengakses elemen ke-0. Cara ini terutama populer pada pemrograman Perl berorientasi objek.
3. STRUKTUR KENDALI
3.1 Blok Statemen
Anda
tidak perlu membaca bagian ini jika Anda seorang programmer C. Blok
statemen adalah rangkaian statemen yang ditempatkan dalam pasangan
kurung kurawal. Bentuknya:
{
....; #statemen pertama
....; #statemen kedua
}Perl mengeksekusi statemen berturut-turut mulai dari yang pertama sampai yang terakhir.
3.2 if dan unless
Bentuk:
if(EXPR)
{
...; #statemen
}
else
{
...: #statemen
}atau:
if(EXPR)
{
...; #statemen
}
elsif(EXPR)
{
...;
}
else
{
...;
}EXPR adalah ekspresi kendali atau kondisional yang dievaluasi dalam konteks boolean (benar atau salah). Blok statemen dieksekusi jika EXPR bernilai benar. Kita dapat menuliskan statemen mendahului if jika statemen hanya satu baris. Contoh:
print "It's there!\n" if ($arrived);selain itu, statemen harus ditulis di dalam blok (tidak seperti pada bahasa C). Sedangkan bentuk penulisan unless sama seperti pada if, di mana unless akan mengeksekusi blok statemen jika EXPR bernilai salah.
3.3 while dan unless
Bentuk:
while(EXPR)
{
...;
}
unless(EXPR)
{
...;
}while akan mengeksekusi blok statemen berulang-ulang selama EXPR bernilai benar, sedangkan unless justru selama EXPR bernilai salah. Kita akan melihat pemakaian while pada pembahasan mengenai I/O dasar.
3.4 for dan foreach
Bentuk penulisan for yang pertama mirip seperti pada C:
for (EXPR_AWAL; KONDISI; EXPR_AKSI)
{
...;
}di mana EXPR_AWAL pertama-tama dieksekusi, lalu berturut-turut blok statemen dan EXPR_AKSI dieksekusi berulang-ulang selama KONDISI terpenuhi. Di sini KONDISI adalah sebuah ekspresi kondisional yang dievaluasi dalam konteks boolean.
Contoh:
for ($i = 1; $i < 11; $i++) {print "$i\n";}Bentuk lain:
for (ARRAY)
{
...;
}Contoh:
for (@scores) {print $_, "\n";}Pada contoh di atas, for mengiterasi array @scores, dan mengeset variabel global $_ ke nilai elemen array yang tengah diakses. $_ adalah variabel global yang secara default dipakai pada banyak operasi, antara lain iterasi array dengan for() seperti ini. Jika kita ingin menggunakan variabel skalar lain bukannya $_, kita gunakan foreach:
foreach $score (@scores) {print $score, "\n";}
4. I/O DASAR
Kita
dapat membuat program yang lebih interaktif, artinya yang dapat
menerima input dari user, dengan membaca dari STDIN. STDIN adalah
filehandle yang disediakan oleh Perl untuk pembacaan dari standard
input. Contoh:
$author = <STDIN>;
print "Author's name: $author";
@book_title = <STDIN>;
for (@book_title) {print join(' ', $_);}Perhatikan bahwa pada konteks array, input akan dibaca terus sampai diterima karakter EOF (Ctrl-D pada Linux). Untuk pemrograman user-interface berbasis teks yang lebih baik, kita dapat menggunakan library curses atau ncurses (new curses) dan modul Curses. Mengenai pemakaian modul akan kita lihat lagi pada bagian Fungsi, Library dan Modul).
Kita sering melihat program yang menerima argumen pada command-line, misalkan cat. Kita menjalankan:
$ cat ppperl.txtdi mana ppperl.txt adalah argumen yang dilewatkan ke program cat. Kita dapat membuat skrip perl kita bekerja seperti itu dengan menggunakan operator berlian (diamond operator) <>. Contoh:
#!/usr/bin/perl
while(<>)
{
print $_;
}Misalkan script di atas kita beri nama pcat, maka jika kita jalankan:
$ pcat ppperl.txtakan bekerja seperti `cat ppperl.txt`.
Operator berlian membaca data dari file yang kita lewatkan sebagai argumen pada command-line, dan while() mengiterasi pembacaan tersebut sampai diterima nilai undef, di mana hasil pembacaan diset secara default ke $_. Pembacaan data dilakukan baris demi baris, dengan kata lain: satu pembacaan dilakukan sampai dijumpai karakter newline ``\n''. Karakter yang menentukan batas satu pembacaan ini disebut dengan: input record separator. Kita dapat mengubah input record separator ini dengan mengeset variabel global $/. Kita akan melihat ini nanti pada bagian mengenai Switch Baris Perintah.
Dengan memanfaatkan $_, kita dapat menulis pcat di atas lebih ringkas lagi:
while(<>)
{
print;
}atau bahkan:
print while(<>);Jika kita melewatkan argumen pada saat memanggil skrip perl kita, maka sebenarnya argumen-argumen tersebut dibaca pada array @ARGV. Misalkan kita punya skrip perl bernama showargs.pl sbb:
#!/usr/bin/perl
print join(", ", @ARGV);dan kita memanggilnya sbb:
$ showargs.pl Camel Llama Panthermaka outputnya: Camel, Llama, Panther
Operator diamond sebenarnya bekerja pada @ARGV ini. Jadi misalkan kita punya file Camel.syn dan Llama.syn yang berturut-turut berisi:
Authoritative Perl reference book by the creator.
---------------
Classic tutorial Perl book by Randal, the JAPH.lalu:
print while(<>);akan mencetak isi file Camel.syn dan Llama.syn berturut-turut.
Untuk mengetahui jumlah argumen yg dilewatkan, manfaatkan variabel $#ARGV. Jadi kalau pada showargs.pl kita tambahkan:
print "\nJumlah argumen yg dilewatkan = ", $#ARGV + 1, "\n";maka: showargs.pl Camel Llama Panther akan menghasilkan output:
Camel, Llama, Panther
Jumlah argumen yg dilewatkan = 3.
5. REGULAR EXPRESSION (perlre)
5.1 Dasar
Jika
kita bekerja dengan word processor, tentunya sudah akrab dengan
fasilitas ``search text'' ataupun ``find and replace.'' Secara
sederhana, regular expression atau regex dapat dipahami sebagai
fasilitas semacam itu, meskipun jauh lebih berdayaguna seperti yang akan
kita lihat nanti. Bagi yang sudah berpengalaman menggunakan grep (=
global regular expression parser), regex Perl menyerupai egrep (extended
grep). Regex yang kita susun adalah berupa pattern (pola) yang terdiri dari sejumlah item. Kita lihat dulu sebuah contoh,
#!/usr/bin/perl
while (<>)
{
print "$_\n" if (/Regular/);
}/Regular/ di dalam if() inilah yang disebut dengan regular expression. Script di atas mencetak baris yang mengandung kata 'Regular'. Cobalah jalankan script di atas terhadap file ppperl.txt ini.
Pola dievaluasi sebagai double-quote string, artinya kita dapat melakukan interpolasi variabel di dalam pola, dan juga dikenali pemakaian control character (ingat pembahasan mengenai double-quote string).
Jika pada contoh di atas kita ingin agar pola dapat cocok dengan Regular maupun Reguler, kita dapat menggunakan character class sbb:
/Regul[ae]r/Jika character class mencakup satu rentang yang panjang, misalkan:
/[0123456789]/ #cocok dengan satu digit bilangankita dapat menuliskannya sbb:
/[0-9]/Bentuk negatifnya kita tuliskan dengan simbol ^ di depan:
/[^0-9]/ #cocok dengan _selain_ satu digit bilanganDengan menggunakan character class, kita pelajari sejumlah konstruk berikut:
Konstruk Nama Ekivalen dengan:
\d digit [0-9]
\w words [a-zA-Z0-9_]
\s whitespaces [ \r\t\n\f]
\D non-digit [^0-9]
\W non-words [^a-zA-Z_]
\S non-whitespaces [^ \r\t\n\f]Untuk pencocokan dengan sembarang karakter kecuali \n, kita gunakan metacharacter titik (.).
5.2 Menggunakan Multiplier
Multiplier
adalah penentu jumlah berapa kali sebuah item muncul. Ini sangat
berguna jika kita ingin menyusun pola pencocokan terhadap item yang
jumlah pemunculannya bervariasi (tidak tetap), atau jumlah pemunculannya
tetap tapi sangat banyak.
Multiplier Arti
* Tidak muncul atau berkali-kali muncul
+ Muncul minimal satu kali
? Tidak muncul atau muncul satu kali
{n} Muncul tepat n kali
{n,} Minimal muncul n kali
{n,m} n =< jumlah pemunculan =< mDengan demikian kita lihat bahwa * ekivalen dengan {0,}, + ekivalen dengan {1,}, dan ? ekivalen dengan {0,1}.
5.3 Tanda Kurung sebagai Memori
Jika
kita gunakan () pada pola pencocokan, maka bagian string yang cocok
dengan pola di dalam tanda kurung tersebut akan disimpan dalam variabel $1 untuk tanda kurung pertama, $2 untuk tanda kurung kedua, dst. Contoh:
@names = ('Larry Wall', 'Es krim Walls');
for (@names)
{
if (/(.+)\sWall/)
{
print "$1\n";
}
}akan mencetak:
Larry
Es krim
5.4 Penjangkaran
Empat konstruk berikut ini berguna untuk ``menjangkarkan'' pola:
Konstruk: Penjangkaran pada:
^ awal baris
$ akhir baris sebelum \n
\b word boundary (batas word)
\B bukan batas wordPerhatikan bahwa ^ memiliki arti yang berbeda jika digunakan di dalam character class atau [], begitu juga \b (di dalam [], \b berarti backspace). \b adalah batas di antara dua karakter, di mana salah satu karakter adalah \w dan karakter lainnya adalah \W (urutan bisa dipertukarkan). Sebaliknya, \B berarti bukan batas word. Untuk jelasnya, lihat ini:
@names = ('Larry Wall', 'Es krim Walls');
for (@names)
{
if (/\bWall\B/)
{
print "$_\n";
}
}akan mencetak:
Es krim Walls
karena pada 'Larry Wall', setelah Wall ada batas word.
5.5 Lebih Jauh dengan Operator-operator Regex
Operator-operator
yang terutama digunakan dengan regex (baca perlop): m//gimosx (seperti
//, tapi dengan m// kita dapat menentukan delimiter non-alfanumerik
selain forward slash, misalkan m## atau m!!), tr///cds (transliterasi:
pemetaan karakter ke karakter lain), s///egimosx (substitusi).
Operator
pencocokan (m// atau //) jika dievaluasi dalam konteks skalar akan
menghasilkan nilai benar (1) jika pencocokan berhasil, atau nilai salah
(null string) jika tidak cocok. Jika dievaluasi dalam konteks array,
akan mengeset elemen array pertama dengan $1, elemen kedua dengan $2,
dst jika pencocokan berhasil. Jika pola pencocokan tidak mengandung
tanda kurung, maka elemen array akan diset 1 jika pencocokan berhasil. Operator substitusi (s///) mengganti bagian string yang cocok dengan pola (di sisi kiri) dengan teks penggantinya (di sisi kanan). Contoh:
@names = ('Larry Wall', 'Es krim Walls');
for (@names)
{
if ($cnt = s/Es krim (Wall)s/Great $1/)
{
print "$_\nJumlah substitusi: $cnt\n";
}
}Keterangan opsi:
g = search secara global, jadi lakukan matching untuk semua pemunculan, bukan hanya sekali saja,
i = case insensitive matching (tidak pedulikan perbedakan huruf kapital/kecil),
m = multiline matching, jadi menerima string yang mengandung banyak \n,
o = compile once, satu kali compile, untuk optimasi kecepatan jika tidak ada interpolasi variabel berulang (lebih dari satu kali) dalam pola pencocokan.
s = single line matching (default),
x = extended regex, jadi boleh menggunakan whitespace (\s) dan comment di dalam regex untuk memudahkan pembacaan,
e = evaluasi sisi kanan sebagai ekspresi. Kalau opsi ini tidak kita cantumkan, maka secara default, sisi kanan (RHS = Right Hand Side) dievaluasi sebagai double-quote string.
Contoh:
$init = "Linux is an OS an OS\n";
$init =~ s/an OS/a kernel/;
print $init; #mencetak: Linux is a kernel an OSKalau kita tambahkan opsi g, seperti ini:
$init =~ s/an OS/a kernel/g;maka outputnya menjadi:
Linux is a kernel a kernelKalau kita ingin agar $init tidak berubah, maka kita dapat meng-assign hasil substitusi ke skalar yang lain. Jika contoh di atas kita ubah:
($end = $init) =~ s/an OS/a kernel/g;
print $end, $init;maka outputnya:
Linux is a kernel a kernel
Linux is an OS an OSBerikut ini adalah sebuah contoh penerapan regex untuk mengoreksi format Nomor Induk Mahasiswa:
Aplikasi basis data di sebuah Perguruan Tinggi dari tahun ke tahun ditulis dalam sistem yang berganti-ganti, oleh orang yang berbeda, dan untuk kebutuhan yang berbeda juga. Ketika diadakan pembenahan sistem, nampak inkonsistensi pada field NIM. Format yang diharapkan adalah dua digit nomor angkatan, titik, dua digit kode program studi, titik, empat digit nomor mahasiswa. Setelah data pada field tersebut dipelajari, dapat dihimpun sample data sebagai berikut (untuk kode prodi tertentu):
91.30. 880
91 30 880
91 30 880
91 880
91.880
91. 880
91 0880
91.0880
91 303
91.30.880
91-30-880
91-30-0880
91.30.0880Karena banyaknya record yang harus diproses (dimulai dengan mahasiswa angkatan 1988), dan terbatasnya kemampuan ``find and replace'' yang dimiliki database, maka diperlukan cara lain. Jika masalah pengaksesan database kita abaikan, dan kita berkonsentrasi pada masalah pengolahan string-nya, cobalah selesaikan dengan regex Perl. Di bawah ini adalah salah satu cara dengan dua baris regex Perl:
while (<>)
{
$prodi = "30";
s/^(\d\d)\D+(\d+)$/$1.$prodi.$2/;
s!^(\d\d)\D(\d\d)\D+(\d+)$!$1.".".$2.".".sprintf("%04d", $3)!e;
print;
};Bingung? Ini adalah bentuk yang lebih mudah dibaca:
while (<>)
{
$prodi = "30";
s/
^
(
\d\d #angkatan
)
\D+ #delimiter
(
\d+ #no. mhs
)
$
/$1.$prodi.$2/x; #sisipkan kode prodi,
#izinkan pencatuman comment dalam matching pattern
s!
^
(
\d\d
)
\D
(\d\d)
\D+ #delimiter antara kode prodi dan nomor
(\d+) #mhs bisa lebih dari satu non-digit char
$
!
$1.".".$2.".".sprintf("%04d", $3) #bentuk kembali dalam format yg benar
!xe; #evaluasi sisi kanan sbg ekspresi
print;
};Regex yang pertama menyisipkan kode prodi, jika data belum mengandung kode prodi, lalu regex kedua memisahkan digit dari non-digit, memformat nomor mhs dalam empat digit, dan menyatukannya kembali dengan delimiter berupa titik. Cobalah mengerjakannya dalam bahasa lain seperti C, Pascal, atau Basic :-)
Jika operator substitusi nampak begitu berdayaguna, namun untuk penggantian karakter lebih efisien menggunakan operator tr///. Contoh:
$_ = "papi pipa da sini.";
tr/ai/ia/;
print "$_\n";akan mencetak:
pipa papi di sana.Opsi-opsi untuk operator tr/// silakan Anda pelajari di perlop.
5.6 Alternasi
Jika
terhadap sebuah string kita ingin mencocokkan lebih dari satu pola,
maka kita gunakan operator alternasi (|). Untuk menggunakan ini kita
harus perhatikan urutan prioritas dari operator maupun item dalam
kaitannya dengan pengelompokan (grouping).
Nama Simbol
--------------------------------
Tanda kurung ()
Multiplier +*?{m,n}
Sequence dan jangkar abc^$\b\B
Alternasi |Berikut ini adalah contoh pemakaian operator alternasi:
/E|Addwin/; #Berbahaya! Lihat output script di bawah
/(E|Ad)dwin/; #cocok dengan Edwin atau Addwin, tapi juga mengeset $1
/(?:E|Ad)dwin/; #seperti di atas, tapi tidak mengeset $1.
/(?:[Ee]|[Aa]d)dwin/; #cocok juga dengan edwin atau addwinUntuk jelasnya, kita coba script berikut:
@names = qw/Eddwin Edwin Ewin Ein Ei En E Addwin edwin addwin Adwin/;
@patts = qw/E|Addwin (E|Ad)dwin (?:E|Ad)dwin (?:[Ee]|[Aa]d)dwin/;
foreach $patt (@patts)
{
for (@names)
{
if (/$patt/)
{
print "/$patt/ cocok dengan $_\n";
if (defined($1)) {print '$1 bernilai: ', "$1\n";}
}
}
}Outputnya:
/E|Addwin/ cocok dengan Eddwin
/E|Addwin/ cocok dengan Edwin
/E|Addwin/ cocok dengan Ewin
/E|Addwin/ cocok dengan Ein
/E|Addwin/ cocok dengan Ei
/E|Addwin/ cocok dengan En
/E|Addwin/ cocok dengan E
/E|Addwin/ cocok dengan Addwin
/(E|Ad)dwin/ cocok dengan Edwin
$1 bernilai: E
/(E|Ad)dwin/ cocok dengan Addwin
$1 bernilai: Ad
/(?:E|Ad)dwin/ cocok dengan Edwin
/(?:E|Ad)dwin/ cocok dengan Addwin
/(?:[Ee]|[Aa]d)dwin/ cocok dengan Edwin
/(?:[Ee]|[Aa]d)dwin/ cocok dengan Addwin
/(?:[Ee]|[Aa]d)dwin/ cocok dengan edwin
/(?:[Ee]|[Aa]d)dwin/ cocok dengan addwin
6. FUNGSI, LIBRARY, DAN MODUL
6.1 Fungsi
Sebuah subrutin atau fungsi memiliki bentuk sebagai berikut:
sub foo
{
........ #tuliskan kode di sini
}di mana foo adalah nama subrutin. Argumen-argumen yang dilewatkan ke subrutin dibaca melalui array @_. Contoh:
sub foo
{
my($arg1, $arg2) = @_;
print "$arg1\n$arg2\n";
}Variabel $arg1 dan $arg2 karena diciptakan melalui my() maka memiliki lingkup (scope) sebatas blok subrutin tersebut. Jika subrutin tersebut perlu mengembalikan nilai, maka nilai tersebut bisa langsung dituliskan di akhir blok. Contoh:
sub banding
{
my($arg1, $arg2) = @_;
$arg1 > $arg2 ? 1 : ($arg1 < $arg2 ? -1 : 0);
}Sebenarnya sebuah subrutin dapat mengembalikan tidak hanya skalar, tapi juga array, array asosiatif, dan beberapa macam lainnya. Untuk pembahasan lebih lengkapnya, baca perlsub. Fungsi sort() yang kita lihat pada pembahasan array di atas dapat kita gunakan dengan lebih fleksibel dengan membuat subrutin yang menentukan aturan sorting. Contoh:
@scores = (68, 50, 30, 78, 5, 58);
@sorted_scores = sort by_num @scores;
print join(' ', @sorted_scores), "\n";
sub by_num
{
banding($a, $b); #subrutin banding() seperti di atas
}Di sini kita lihat bahwa subrutin yang dilewatkan ke sort() memiliki keistimewaan yaitu diciptakannya secara otomatis variabel global $a dan $b yang berisi dua elemen array yang akan dibandingkan. Untuk lebih efisien lagi, kita dapat gunakan operator ``piring terbang'' (spaceship operator), sehingga subrutin by_num menjadi:
sub by_num
{
$a <=> $b; #operator spaceship
}Cobalah membuat sorting descending (dari besar ke kecil) dari array @scores di atas.
Berikut ini adalah contoh lain penerapan sort(). Jika sebuah record disimpan sebagai sebuah array anonim, dengan elemen berturut-turut: nama, skor, dan umur, dan record-record tersebut akan di-sort dengan kriteria pertama nilai tertinggi, kriteria kedua umur, dan kriteria ketiga nama siswa, maka kita dapat mengimplementasikannya sebagai berikut:
@students = (['joko', 60, 18],
['kabayan', 50, 20],
['acong', 50, 20],
['sitorus', 70, 20],
['ali', 70, 18]);
sub by_rank
{
$b->[1] <=> $a->[1] || $a->[2] <=> $b->[2] || $a->[0] cmp $b->[0];
}
@students = sort by_rank @students;
for (@students)
{
print $_->[0], ' ', $_->[1], ' ', $_->[2], "\n";
}
6.2 Library dan Modul
Sebelum
OOP (Object Oriented Programming) dimasukkan ke Perl, library adalah
cara yang terutama dipakai untuk menangani pemakaian kode secara
berulang. Perbedaan utama antara library dan modul terletak pada
enkapsulasi. Untuk menggunakan sebuah library, gunakan require. Contoh:
require "find.pl";Sedangkan untuk menggunakan sebuah modul, kita biasanya menggunakan use, meskipun sebenarnya bisa juga menggunakan require (dengan beberapa perbedaan penting, untuk jelasnya baca perlfaq8).
Saat ini modul dirasakan lebih memadai karena semakin kuatnya kecenderungan untuk menggunakan perl pada pengembangan aplikasi-aplikasi besar, dan semakin banyaknya kode OOP (yang membutuhkan enkapsulasi yang memadai, yang mana hal ini didukung pada pemakaian modul). Daftar modul ``resmi'' dapat dilihat pada situs CPAN (Comprehensive Perl Archive Network) http://www.perl.com/CPAN-local/.
Dokumentasi sebuah modul biasanya menyatu (embedded) pada modul tersebut, dan ditulis dalam format pod. Sebagai contoh, misalkan kita ingin membaca dokumentasi modul Getopt::Std, maka:
$ perldoc Getopt::StdSimbol :: berkaitan dengan letak modul tersebut di dalam direktori lib Perl. Cobalah Anda jalankan:
$ perl -Vdan lihat array @INC yang berisi direktori-direktori di mana Perl akan mencari modul yang akan digunakan. Anda akan melihat subdirektori Getopt dalam salah satu dari direktori tersebut, dan subdir Getopt ini berisi file Std.pm.
Sekarang kita akan menggunakan modul Getopt::Std untuk memproses switch pada baris perintah (command-line). Modul ini juga mendukung clustering (pengelompokan) switch.
#!/usr/bin/perl
use Getopt::Std;
$options = 'o:n:d:f';
getopts $options or die;
print $opt_o, "\n";
print $opt_n, "\n";
print $opt_d, "\n";
print $opt_f, "\n";
edwin@skserver:~>> usestd -foMf -nmf -d/var/lib/
Mf
mf
/var/lib/
1Pada contoh di atas kita melihat switch clustering pada -fo yang sebenarnya adalah dua switch yang terpisah: -f -o. Perhatikan $options yang berisi switch apa saja yang akan digunakan. Switch yang membutuhkan argumen dituliskan dengan diikuti colon (:), sedangkan switch yang tidak membutuhkan argumen (disebut sebagai boolean flag), ditulis tanpa diikuti colon. Pada contoh di atas, switch -f adalah boolean flag.
Lebih baik adalah dengan menggunakan hash:
#!/usr/bin/perl
use Getopt::Std;
$options = 'o:n:d:f';
%options = ();
getopts($options, \%options) or die;
for (sort keys %options)
{
print "$_: ", $options{$_}, "\n";
}yang jika dijalankan sebagai script usestd1, hasilnya adalah:
edwin@skserver:~>> usestd1 -foMf -nmf -d/var/lib/
d: /var/lib/
f: 1
n: mf
o: Mf
7. SWITCH BARIS-PERINTAH (perlrun)
Perl
memiliki sejumlah pilihan atau opsi yang dapat kita tentukan dengan
melewatkan switch baris-perintah pada interpreter perl. Di sini kita
lihat beberapa switch yang banyak digunakan.
-vmencetak versi perl yang terinstall
-Vmencetak konfigurasi perl pada sistem Anda
-cCompile only, check syntax error.
-wWarning.
-nKita dapat membuat skrip yang bekerja seperti program cat, sebagai berikut:
#!/usr/bin/perl
while(<>)
{
print;
}Dengan opsi -n, kita dapat menulis skrip di atas menjadi lebih singkat:
#!/usr/bin/perl -n
print;
-pOpsi ini mirip seperti -n, bedanya ia juga melakukan print $_ pada akhir blok while, sehingga kita dapat menulis ulang skrip di atas menjadi:
#/usr/bin/perl -p
-eDengan switch ini, perl tidak akan mencari namafile script, dan sebaliknya akan langsung mengeksekusi baris yang mengikutinya. Contoh:
$ perl -ne 'print' Camel.syn Llama.synatau:
$ perl -pe '' Camel.syn Llama.synakan mencetak isi file Camel.syn dan Llama.syn
-0Digunakan untuk menentukan input record separator berupa bilangan oktal. Efeknya seperti mengeset $/ (yang default-nya adalah \n). Misalkan:
$ perl -n00 -e 'print "Record ke-", ++$i, ":\n$_\n"' ppperl.txtSwitch -00 akan mengeset $/ = ``'', atau blank-line. Jika pergantian paragraph ditandai dengan satu baris kosong (blank-line), maka pembacaan satu record akan sama dengan pembacaan satu paragraph. Maka dari itu sering dikatakan bahwa switch -00 mengaktifkan modus paragraf. Nilai -0777 akan membaca seluruh isi file sebagai satu record.
-iBerguna untuk melakukan pengubahan langsung pada teks yang sedang diolah. Misalkan kita punya script berikut bernama rmcr:
#!/usr/bin/perl -p
s/\r\n/\n/;yang membuang karakter CR (Carriage Return) pada akhir baris sebuah file teks, maka untuk menggunakannya adalah sbb:
$ rmcr the_file.txt > the_file.newLebih baik kalau pengubahan itu dilakukan langsung terhadap the_file.txt, dan ini dapat dilakukan dengan opsi -i.
$ perl -pi.old -e 's/\r\n/\n/' the_file.txt.old yang mengikuti opsi -i akan menentukan ekstensi bagi file backup yang diciptakan. Dengan cara demikian, maka perubahan (pembuangan karakter CR) langsung berpengaruh pada the_file.txt, dan juga diciptakan file the_file.txt.old sebagai backup dari the_file.txt yang lama.
-dmengaktifkan symbolic debugger perl.
8. PENUTUP
Saat
ini pemakaian Perl telah berkembang pesat pada berbagai platform
(http://www.perl.org/cgi-bin/survey/): AIX, Amiga, Digital UNIX,
FreeBSD, HP-UX, IRIX, Linux, OS/2, Solaris, Win32, (dan masih banyak
lagi), dan untuk berbagai keperluan yang sama sekali tidak terbayangkan
ketika ia diciptakan.
Masih banyak yang belum tercakup dalam
teks ini yang sekedar bermaksud menyediakan pengetahuan awal bagi orang
yang ingin mengenal Perl lebih dalam. Penulis menyarankan sebagai bacaan
lebih lanjut adalah buku-buku klasik seperti Programming Perl (Larry
Wall dan Randal Schwartz), Learning Perl (Randal Schwartz dan Tom
Christiansen), Advanced Perl Programming (Sriram Srinivasan), meskipun
sulit didapat dan muahall :-( Juga wajib dipelajari adalah perlfaq.
Perlu rajin dipelajari adalah perl manpage. 9. APPENDIX
A. Membaca perlop
Appendix ini ditujukan untuk membantu mempelajari perlop, yaitu manual Perl yang membahas operator-operator.
Dari
jumlah operand-nya, dibedakan jenis-jenis operator unary (1 operand),
binary (2 operand), dan ternary (3 operand). Fungsi (subrutin) bisa
ditulis sebagai operator unary, sebagai contoh: chdir("new-dir"); #sebagai fungsi
chdir "new-dir"; #sebagai operatorMaka dari itu, dalam perlop kita menjumpai istilah operator unary bernama untuk menyebut operator-operator yang juga bisa digunakan sebagai fungsi, dan operator unary simbolik. Contoh operator unary simbolik adalah ++, dan --.
Operator-operator tertentu menerima operand berupa list (array), sehingga dikenal juga istilah operator list. Sebagai contoh adalah fungsi atau operator print:
print('Cuma contoh.', "\n"); #sebagai fungsi
print 'Cuma contoh.', "\n"; #sebagai operatorKemudian pada bagian SYNOPSIS di perlop, kita melihat tabel tingkat prioritas (precedence) dan asosiativitas. Entri teratas adalah operator-operator dengan tingkat prioritas paling tinggi. Asosiativitas menjadi penting kalau sebuah ekspresi melibatkan beberapa operator yang tingkat prioritasnya sama. Untuk jelasnya, kita lihat entri teratas dari tabel tersebut:
left terms and list operators (leftward)Ini berarti bahwa term dan operator-operator list memiliki asosiativitas left, yaitu evaluasi akan dilakukan dari kiri ke kanan. Kemudian ada catatan juga bahwa precedence dan asosiativitas tersebut berlaku untuk operator list dilihat dari sisi kiri (leftward). Jika kita perhatikan dalam tabel tersebut, operator list muncul lagi dengan tingkat prioritas yang jauh lebih rendah, jika dilihat dari sisi kanan (rightward). Contoh:
@ary = (0, 3, sort 4, 2, 1);Penjelasan: sort termasuk operator list. Di sisi kanan (rightward), sort memiliki tingkat prioritas yg lebih rendah daripada operator koma, maka operator koma akan terlebih dulu membentuk array berisi elemen 4, 2, 1. Kemudian, di sisi kiri-nya (leftward), sort memiliki tingkat prioritas yang sangat tinggi, sehingga operasi sort dilakukan terlebih dulu terhadap array yang berisi 4, 2, dan 1. Selanjutnya barulah operator koma membentuk array berisi elemen 1, 3, dan hasil sort (1, 2, dan 4), yang selanjutnya disimpan dalam @ary.
Yang termasuk dalam term antara lain adalah variabel, operator-operator quote, ekspresi yang dituliskan dalam tanda kurung, dan fungsi. Contoh:
@ary = (0, 3, sort(4, 2), 1);
for(@ary){print "$_ ";}menghasilkan: 0, 3, 2, 4, 1.
B. URL-URL
Berikut ini adalah beberapa URL berkaitan dengan Perl:
Situs-situs utama: http://www.perl.com/
http://language.perl.com/
http://republic.perl.com/
http://www.perl.org/
The Perl Journal, memuat juga arsip kontes-kontes yang pernah diselenggarakan: http://www.tpj.com/
Perl Mongers, users groups Perl: http://www.pm.org.
Untuk wilayah Semarang dan sekitarnya: http://lumpia.pm.org/ (contoh situs web yang dibuat oleh lazy programmer :-)
Perl/Tk, pemrograman X-Window dengan Perl:
http://www.personal.u-net.com/~ni-s/ (Nick Ing-Simmons),
http://www.connect.net/gbarr/ (Graham Barr),
http://user.cs.tu-berlin.de/~eserte/ (Slaven Rezic),
http://mysite.directlink.net/gbarr/PerlTk/tk-modlist.htm (Perl/Tk module list),
http://www.lehigh.edu/~sol0/ (Stephen O. Lidie).
Proyek integrasi web server Apache dengan Perl: http://perl.apache.org/mod_perl
Kolom Randal L. Schwartz di WebTechniques: http://www.stonehenge.com/merlyn/WebTechniques/
Jeffrey Friedl, sang regex Guru: http://enterprise.ic.gc.ca/~jfriedl/perl
Far More Than Everything You've Ever Wanted To Know (about Perl): http://language.perl.com/CPAN/doc/FMTEYEWTK/index.html
ref: http://unilanet.unila.ac.id/~gigih/index.php?option=com_content&task=view&id=108&Itemid=109
Tidak ada komentar:
Posting Komentar