Home > Old Post dari Unilanet > Mari Belajar PERL

Mari Belajar PERL


  • NAME
  • SYNOPSIS
  • 1. PENDAHULUAN
    • 1.1 Apa Itu Perl?
    • 1.2 Membuat dan Mengeksekusi Program Perl
    • 1.3 Dokumentasi Perl (perlpod)
  • 2. DATA
    • 2.1 Skalar
    • 2.2 Array
    • 2.3 Array Asosiatif
    • 2.4 Konteks
    • 2.5 Referensi dan Variabel Anonim
  • 3. STRUKTUR KENDALI
    • 3.1 Blok Statemen
    • 3.2 if dan unless
    • 3.3 while dan unless
    • 3.4 for dan foreach
  • 4. I/O DASAR
  • 5. REGULAR EXPRESSION (perlre)
    • 5.1 Dasar
    • 5.2 Menggunakan Multiplier
    • 5.3 Tanda Kurung sebagai Memori
    • 5.4 Penjangkaran
    • 5.5 Lebih Jauh dengan Operator-operator Regex
    • 5.6 Alternasi
  • 6. FUNGSI, LIBRARY, DAN MODUL
    • 6.1 Fungsi
    • 6.2 Library dan Modul
  • 7. SWITCH BARIS-PERINTAH (perlrun)
  • 8. PENUTUP
  • 9. APPENDIX
    • A. Membaca perlop
    • B. URL-URL
  • 10. PENULIS DAN COPYRIGHT


NAME

PPP – Pintu Pertama ke Perl (bukan Point to Point Protocol, apalagi Partai Persatuan Pembangunan)

$Id: ppperl.pod,v 1.7 1999/03/29 16:55:48 edwin Exp $


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/perl

Simpanlah 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 perlfaq

Tersedia 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.html

Sedangkan untuk membuat ASCII Text:

 $ pod2text perlfaq1.pod > perlfaq1.txt

Untuk 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 numerik

Perhatikan 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     tab

Interpolasi 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 Friedl

Basis 0 ini sebenarnya dapat diubah dengan cara mengubah nilai $[. Contoh:

 $[ = 1; #more convenient to awk folks
 print $authors[1], "\n"; #mencetak Larry

Sekalipun 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 array

Konteks 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
 HASH

Untuk 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.txt

di 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.txt

akan 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 Panther

maka 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 bilangan

kita dapat menuliskannya sbb:

 /[0-9]/

Bentuk negatifnya kita tuliskan dengan simbol ^ di depan:

 /[^0-9]/        #cocok dengan _selain_ satu digit bilangan

Dengan 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 =< m

Dengan 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 word

Perhatikan 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 OS

Kalau kita tambahkan opsi g, seperti ini:

 $init =~ s/an OS/a kernel/g;

maka outputnya menjadi:

 Linux is a kernel a kernel

Kalau 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 OS

Berikut 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.0880

Karena 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 addwin

Untuk 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::Std

Simbol :: berkaitan dengan letak modul tersebut di dalam direktori lib Perl. Cobalah Anda jalankan:

 $ perl -V

dan 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/
 1

Pada 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.

 -v

mencetak versi perl yang terinstall

 -V

mencetak konfigurasi perl pada sistem Anda

 -c

Compile only, check syntax error.

 -w

Warning.

 -n

Kita 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;
 -p

Opsi 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
 -e

Dengan switch ini, perl tidak akan mencari namafile script, dan sebaliknya akan langsung mengeksekusi baris yang mengikutinya. Contoh:

 $ perl -ne 'print' Camel.syn Llama.syn

atau:

 $ perl -pe '' Camel.syn Llama.syn

akan mencetak isi file Camel.syn dan Llama.syn

 -0

Digunakan 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.txt

Switch -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.

 -i

Berguna 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.new

Lebih 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.

 -d

mengaktifkan 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 operator

Maka 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 operator

Kemudian 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


10. PENULIS DAN COPYRIGHT

Copyright (c) 1999, Edwin Pratomo. All rights reserved. Send any comments, suggestions to

ed.pratomo@computer.org.
This email address is being protected from spam bots, you need Javascript enabled to view it

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: