Masukan dari pengguna command line dibaca melalui STDIN, dan setiap baris yang terbaca membawa karakter baris baru di ujungnya. Karakter itu ikut tersimpan bersama teksnya, sehingga teks yang belum dipangkas sering merusak sapaan, perbandingan, dan pencatatan. Topik ini membahas operator <STDIN> untuk membaca baris, disiplin chomp untuk memangkas baris baru tersebut, serta perilaku chomp ketika tidak ada baris baru yang dapat dipangkas.
Membaca satu baris dengan STDIN#
Operator <STDIN> dalam konteks scalar menghasilkan satu baris berikutnya dari masukan standar, termasuk karakter baris barunya. Konteks scalar terbentuk ketika hasilnya langsung ditugaskan ke variabel skalar, sehingga pernyataan my $nama = <STDIN>; menunggu satu baris masukan lalu menyimpannya beserta baris barunya. Baris yang dihasilkan mengikuti urutan masukan, yaitu baris pertama pada pemanggilan pertama dan baris berikutnya pada setiap pemanggilan selanjutnya. Pembacaan berhenti pada karakter baris baru pertama yang ditemukan, sehingga satu pemanggilan tidak pernah mengambil lebih dari satu baris, dan sisa masukan tetap tersedia bagi pemanggilan berikutnya. Apabila masukan sudah habis, <STDIN> menghasilkan undef, yaitu nilai yang belum terisi, sehingga variabel tujuannya kosong dan pemakaiannya memicu peringatan.
Skrip berikut menanyakan sebuah nama, membaca satu baris masukan, memangkas baris barunya dengan chomp, kemudian mencetak sapaan:
# tidak-dijalankan: skrip ini menunggu masukan, jalankan lewat pipe seperti contoh bash di bawah
use strict;
use warnings;
print "Masukkan sebuah nama: ";
my $nama = <STDIN>;
chomp $nama;
print "Selamat datang, $nama.\n";Karena skrip ini menunggu masukan, pengujian dilakukan dengan mengalirkan keluaran echo menuju STDIN skrip melalui pipe. Jalankan perintah berikut:
# menjalankan salam.pl dengan masukan yang disodokan lewat pipe
echo "Ali" | perl salam.pl 2>&1Masukkan sebuah nama: Selamat datang, Ali.Prompt Masukkan sebuah nama: tidak diakhiri baris baru, sehingga sapaan menyambung pada baris yang sama. Pada pemakaian interaktif di terminal, prompt itulah yang muncul, dan kursor menunggu ketikan sampai tombol enter ditekan. Baris yang diketik tersedia bagi <STDIN> setelah tombol enter ditekan, karena baris baru itulah penanda berakhirnya satu baris masukan. Nama Ali yang diketik tadi muncul kembali tanpa baris barunya berkat chomp, sehingga tanda titik penutup sapaan menempel dengan benar.
Baris baru yang lolos tanpa chomp#
Tanpa chomp, karakter baris baru ikut tersimpan di akhir variabel dan ikut tercetak ketika teks digabungkan. Perintah berikut membuang chomp dari kode yang sama:
# tanpa chomp, baris baru dari masukan ikut tersimpan
echo "Ali" | perl -e 'use strict; use warnings; my $nama = <STDIN>; print "Selamat datang, $nama!\n"' 2>&1Selamat datang, Ali
!Tanda seru jatuh ke baris kedua karena $nama berisi Ali diikuti baris baru yang berasal dari masukan, bukan dari teks program. Perbandingan seperti $nama eq "Ali" juga menghasilkan keputusan yang salah, karena teks yang tersimpan sesungguhnya adalah Ali\n. Baris baru yang lolos ikut terhitung dalam panjang teks, karena length($nama) membacanya sebagai satu karakter. Karakter itu berasal dari pemisah baris pada masukan, bukan dari baris kode mana pun, sehingga penyebabnya tidak terlihat pada teks program. Versi dengan chomp memberikan hasil yang benar:
# dengan chomp, baris baru dipangkas sebelum teks dipakai
echo "Ali" | perl -e 'use strict; use warnings; my $nama = <STDIN>; chomp $nama; print "Selamat datang, $nama!\n"' 2>&1Selamat datang, Ali!chomp memangkas satu karakter baris baru di ujung variabel apabila karakter itu ada. Apabila tidak ada, variabel dibiarkan apa adanya dan tidak ada pesan yang muncul. Perilaku yang aman ini membuat chomp boleh dipanggil tanpa memeriksa isi variabel terlebih dahulu. Karena itu pula chomp tidak boleh diganti dengan chop, yang menghapus karakter terakhir apa pun bentuknya dan merusak teks yang memang tidak berakhir dengan baris baru.
chomp pada variabel dan array#
Perilaku tanpa-pesan itu diuji langsung dengan skrip berikut, yang memanggil chomp dua kali pada variabel yang sama:
#!/usr/bin/env perl
use strict;
use warnings;
my $teks = "Perl\n";
chomp $teks;
print "Pangkasan pertama: [$teks]\n";
chomp $teks;
print "Pangkasan kedua: [$teks]\n";Pangkasan pertama: [Perl]
Pangkasan kedua: [Perl]Pangkasan pertama menghapus baris baru yang melekat pada "Perl\n". Pangkasan kedua tidak menemukan baris baru lagi dan membiarkan $teks apa adanya, sehingga kedua baris keluaran identik. chomp bekerja langsung pada variabel yang diberikan kepadanya, tanpa menghasilkan variabel baru, dan tidak menimbulkan peringatan ketika tidak ada yang dipangkas. Karakter yang dipangkas cocok dengan pemisah rekaman masukan yang tersimpan pada variabel $/, dan nilai defaultnya berupa satu karakter baris baru. Nilai balik chomp sebenarnya berupa banyaknya karakter yang dipangkas, tetapi nilainya jarang digunakan karena teks yang dibersihkan sudah berubah langsung pada variabelnya.
chomp juga menerima array, dan seluruh elemennya dipangkas dalam satu pemanggilan:
# chomp memangkas baris baru pada seluruh elemen array sekaligus
printf "apel\njeruk\n" | perl -e 'use strict; use warnings; my @buah = <STDIN>; chomp @buah; print "@buah\n"' 2>&1apel jerukMasukan yang terdiri atas dua baris terbaca sekaligus ke dalam @buah, kemudian chomp @buah membersihkan setiap elemen. Kombinasi my @baris = <STDIN>; dan chomp @baris; menjadi pola baku untuk memindahkan seluruh masukan ke memori tanpa baris baru. Satu elemen hasil pembacaan tetap perlu dipangkas satu kali, dan disiplin ini berlaku pada setiap skrip yang menggunakan masukan.
Kesalahan umum#
- Baris masukan digunakan tanpa dipangkas terlebih dahulu. Nilai
$namasetelah pembacaan sesungguhnya berisiAlidiikuti baris baru, sehingga perbandingan$nama eq "Ali"menghasilkan keputusan yang salah tanpa pesan apa pun. Panggilchomp $namatepat setelah baris terbaca, sebelum teksnya digunakan. - Baris baru diasumsikan otomatis ditambahkan oleh
print. Fungsi ini mengirim teks apa adanya, sehingga dua keluaran yang dicetak berurutan menempel apabila baris baru lupa ditulis pada akhir teks pertama. Tulis\nsendiri pada posisi yang memerlukan baris baru. - Skrip pembaca masukan dijalankan tanpa pipe sehingga tampak berhenti. Program tidak mengalami error, melainkan menunggu ketikan dari masukan standar. Uji dengan
echo "Ali" | perl salam.pl, atau ketik jawaban di terminal lalu akhiri dengan menekan enter.
Ringkasan#
<STDIN>dalam konteks scalar menghasilkan satu baris lengkap dengan baris barunya, sedangkan dalam konteks list menghasilkan seluruh baris masukan.chompmemangkas satu baris baru di ujung variabel apabila ada, dan membiarkan variabel apa adanya apabila tidak ada.chompdapat diterapkan pada seluruh elemen array sekaligus dalam satu pemanggilan.- Masukan pengujian dialirkan melalui pipe, misalnya
echo "Ali" | perl salam.pl, sehingga skrip tidak menunggu ketikan.
Referensi#
- perlfunc — Perl documentation — Dokumentasi chomp dan readline yang menjadi dasar pembacaan STDIN.
- perlop — Perl documentation — Operator I/O yang menjelaskan perilaku <> pada masukan standar.