Cukup mudah untuk membaca isi garis file teks Linux demi baris dalam skrip shell - selama Anda berurusan dengan beberapa gotcha yang halus. Inilah cara melakukannya dengan cara yang aman.
File, teks, dan idiom
Setiap bahasa pemrograman memiliki seperangkat idiom. Ini adalah cara standar, tanpa embel-embel untuk mencapai serangkaian tugas umum. Mereka adalah cara dasar atau default untuk menggunakan salah satu fitur bahasa yang sedang dilakukan oleh programmer. Mereka menjadi bagian dari toolkit programmer dari cetak biru mental.
Tindakan seperti membaca data dari file, bekerja dengan loop, dan menukar nilai dari dua variabel adalah contoh yang baik. Programmer akan tahu setidaknya satu cara untuk mencapai tujuan mereka secara umum atau vanila. Mungkin itu akan cukup untuk persyaratan yang dihadapi. Atau mungkin mereka akan memperindah kode untuk membuatnya lebih efisien atau berlaku untuk solusi spesifik yang sedang mereka kembangkan. Tetapi memiliki idiom blok bangunan di ujung jari mereka adalah titik awal yang bagus.
Mengetahui dan memahami idiom dalam satu bahasa membuatnya lebih mudah untuk mengambil bahasa pemrograman baru juga. Mengetahui bagaimana hal-hal dibangun dalam satu bahasa dan mencari yang setara - atau yang paling dekat dengan bahasa lain adalah cara yang baik untuk menghargai persamaan dan perbedaan antara bahasa pemrograman yang sudah Anda ketahui dan yang Anda pelajari.
Membaca garis dari file: satu-liner
Di bash, Anda dapat menggunakan a
ketika
Loop pada baris perintah untuk membaca setiap baris teks dari file dan lakukan sesuatu dengannya. File teks kami disebut "data.txt." Itu memegang daftar bulan dalam setahun.
Januari Februari berbaris . . Oktober November Desember
Satu-liner sederhana kami adalah:
saat membaca baris; lakukan echo $ line; selesai & lt; data.txt
NS
ketika
Loop membaca garis dari file, dan aliran eksekusi program kecil melewati tubuh loop. NS
gema
Perintah menulis garis teks di jendela terminal. Upaya baca gagal ketika tidak ada lagi garis yang akan dibaca, dan loop selesai.
Satu trik rapi adalah kemampuannya untuk mengarahkan file ke dalam loop . Dalam bahasa pemrograman lain, Anda harus membuka file, baca darinya, dan tutup lagi saat Anda selesai. Dengan bash, Anda cukup menggunakan pengalihan file dan membiarkan shell menangani semua hal tingkat rendah untuk Anda.
Tentu saja, satu-liner ini tidak terlalu berguna. Linux sudah menyediakan
kucing
perintah, yang melakukan hal itu untuk kita. Kami telah membuat cara berlapis panjang untuk mengganti perintah tiga huruf. Tetapi itu jelas menunjukkan prinsip-prinsip membaca dari file.
Itu bekerja dengan cukup baik, hingga satu titik. Misalkan kita memiliki file teks lain yang berisi nama bulan. Dalam file ini, urutan pelarian untuk karakter baris baru telah ditambahkan ke setiap baris. Kami akan menyebutnya "Data2.txt."
Januari \ n Februari \ N. Maret \ N. . . Oktober \ N. November \ N. Desember \ n
Mari kita gunakan satu-liner kami pada file baru kami.
saat membaca baris; lakukan echo $ line; selesai & lt; data2.txt
Karakter pelarian backslash "
\
"Telah dibuang. Hasilnya adalah bahwa "n" telah ditambahkan ke setiap baris. Bash menafsirkan backslash sebagai awal dari sebuah
urutan pelarian
. Seringkali, kami tidak ingin bash untuk menafsirkan apa yang dibaca. Dapat lebih nyaman untuk membaca garis dalam urutan pelarian keseluruhan backslash dan semua - dan memilih apa yang akan diuraikan atau ganti sendiri, dalam kode Anda sendiri.
Jika kita ingin melakukan pemrosesan atau penguraian yang berarti pada garis-garis teks, kita perlu menggunakan skrip.
Membaca garis dari file dengan skrip
Ini skrip kami. Ini disebut "script1.sh."
#! / Bin / Bash
counter = 0
Sementara IFS = '' Baca -R ] || [ -N " $ {linefromfile} ] ]; lakukan
(( counter ++ ))
Echo "mengakses garis $ counter $ {linefromfile} ]
Selesai & lt; " $ 1
Kami menetapkan variabel yang disebut
Menangkal
ke nol, maka kita mendefinisikan kita
ketika
lingkaran.
Pernyataan pertama pada baris sementara adalah
IFS = ''
.
IFS.
singkatan dari pemisah bidang internal. Ini menampung nilai-nilai yang digunakan bash untuk mengidentifikasi batas kata. Secara default, perintah Read Command Off memimpin dan menunggas spasi. Jika kita ingin membaca garis dari file persis seperti sebelumnya, kita perlu mengatur
IFS.
menjadi string kosong.
Kita bisa mengatur ini sekali di luar loop, sama seperti kita menetapkan nilai
Menangkal
. Tetapi dengan skrip yang lebih kompleks - terutama mereka yang memiliki banyak fungsi yang ditentukan pengguna di dalamnya - mungkin saja itu
IFS.
dapat diatur ke nilai yang berbeda di tempat lain dalam skrip. Memastikan hal itu
IFS.
diatur ke string kosong setiap kali
ketika
Loop iterate menjamin bahwa kita tahu apa perilakunya.
Kita akan membaca garis teks ke dalam variabel yang disebut
Linefromfile.
. Kami menggunakan
-R
(baca backslash sebagai karakter normal) Opsi untuk mengabaikan backslash. Mereka akan diperlakukan sama seperti karakter lain dan tidak akan menerima perawatan khusus.
Ada dua kondisi yang akan memuaskan
ketika
loop dan biarkan teks diproses oleh tubuh loop:
-
baca -r linefromfile.: Ketika garis teks berhasil dibaca dari file,Bacaperintah mengirimkan sinyal kesuksesan keketika, danketikaLoop meneruskan aliran eksekusi ke tubuh loop. Perhatikan bahwaBacaPerintah perlu melihat a karakter baris baru Di akhir baris teks untuk menganggapnya berhasil dibaca. Jika file bukan a POSIX. File teks yang sesuai, Baris terakhir mungkin tidak termasuk karakter baris baru . Jika ituBacaperintah melihat akhir penanda file (EOF) sebelum garis dihentikan oleh baris baru, itu akan bukan perlakukan itu sebagai bacaan yang berhasil. Jika itu terjadi, baris terakhir teks tidak akan diteruskan ke tubuh loop dan tidak akan diproses. -
[-N "$ {linefromfile}"]: Kita perlu melakukan beberapa pekerjaan tambahan untuk menangani file yang kompatibel dengan non-POSIX. Perbandingan ini memeriksa teks yang dibaca dari file. Jika tidak diakhiri dengan karakter baris baru, perbandingan ini akan tetap kembali sukses keketikalingkaran. Ini memastikan bahwa fragmen garis trailing diproses oleh tubuh loop.
Dua klausa ini dipisahkan oleh operator logis "
||
"Sehingga jika
salah satu
Klausul mengembalikan kesuksesan, teks yang diambil diproses oleh tubuh loop, apakah ada karakter baris baru atau tidak.
Dalam tubuh loop kami, kami menambah
Menangkal
variabel dengan satu dan menggunakan
gema
untuk mengirim beberapa output ke jendela terminal. Nomor garis dan teks dari setiap baris ditampilkan.
Kita masih bisa menggunakan trik pengalihan kita untuk mengarahkan file ke dalam loop. Dalam hal ini, kami mengalihkan $ 1, variabel yang menyimpan nama parameter baris perintah pertama yang diteruskan ke skrip. Dengan menggunakan trik ini, kita dapat dengan mudah meneruskan nama file data yang kita inginkan agar skrip berfungsi.
Salin dan tempel skrip ke editor dan simpan dengan nama file "script1.sh." Menggunakan
chmod.
memerintah
Untuk membuatnya dapat dieksekusi
.
chmod + x script1.sh
Mari kita lihat apa yang dimanfaatkan skrip kami dari file teks data2.txt dan backslash yang terkandung di dalamnya.
./ script1.sh data2.txt
Setiap karakter dalam baris ditampilkan Verbatim. Backslashes tidak ditafsirkan sebagai karakter pelarian. Mereka dicetak sebagai karakter biasa.
Melewati garis ke suatu fungsi
Kami masih menggemakan teks ke layar. Dalam skenario pemrograman dunia nyata, kami kemungkinan akan melakukan sesuatu yang lebih menarik dengan garis teks. Dalam kebanyakan kasus, ini adalah praktik pemrograman yang baik untuk menangani pemrosesan lebih lanjut dari garis dalam fungsi lain.
Inilah cara kita bisa melakukannya. Ini adalah "script2.sh."
Kami mendefinisikan kami
Menangkal
variabel seperti sebelumnya, dan kemudian kita mendefinisikan fungsi yang disebut
proses_line ()
. Definisi suatu fungsi harus muncul
sebelum
Fungsi ini pertama kali dipanggil dalam skrip.
Fungsi kami akan lulus baris teks yang baru dibaca di setiap iterasi
ketika
lingkaran. Kita dapat mengakses nilai itu dalam fungsi dengan menggunakan
$ 1.
variabel. Jika ada dua variabel yang diteruskan ke fungsi, kita dapat mengakses nilai-nilai tersebut menggunakan
$ 1.
dan
$ 2.
, dan sebagainya untuk lebih banyak variabel.
W.
hile
Loop terutama sama. Hanya ada satu perubahan di dalam tubuh loop. NS
gema
garis telah diganti dengan panggilan ke
proses_line ()
fungsi. Perhatikan bahwa Anda tidak perlu menggunakan kurung "()" atas nama fungsi ketika Anda meneleponnya.
Nama variabel memegang garis teks,
Linefromfile.
, dibungkus tanda kutip ketika diteruskan ke fungsi. Ini melayani garis yang memiliki ruang di dalamnya. Tanpa tanda kutip, kata pertama diperlakukan sebagai
$ 1.
oleh fungsi, kata kedua dianggap
$ 2.
, dan seterusnya. Menggunakan tanda kutip memastikan bahwa seluruh baris teks ditangani, sama sekali, sebagai
$ 1.
. Perhatikan bahwa ini
bukan
sama
$ 1.
yang memegang file data yang sama diteruskan ke skrip.
Karena
Menangkal
telah dinyatakan dalam badan utama skrip dan bukan di dalam fungsi, itu dapat direferensikan di dalam
proses_line ()
fungsi.
Salin atau ketik skrip di atas ke editor dan simpan dengan nama file "script2.sh." Membuatnya dapat dieksekusi dengan
chmod.
:
chmod + x script2.sh
Sekarang kita dapat menjalankannya dan meneruskan file data baru, "Data3.txt." Ini memiliki daftar bulan di dalamnya, dan satu baris dengan banyak kata di atasnya.
Januari Februari berbaris . . Oktober November \ Nmore Text "di ujung baris" Desember
Perintah kami adalah:
./ script2.sh data3.txt
Garis-garis dibaca dari file dan melewati satu per satu ke
proses_line ()
fungsi. Semua garis ditampilkan dengan benar, termasuk yang aneh dengan backspace, tanda kutip, dan beberapa kata di dalamnya.
Blok bangunan berguna
Ada kereta pemikiran yang mengatakan bahwa idiom harus mengandung sesuatu yang unik untuk bahasa itu. Itu bukan keyakinan bahwa saya berlangganan. Yang penting adalah bahwa itu membuat penggunaan bahasa, mudah diingat, dan memberikan cara yang andal dan kuat untuk mengimplementasikan beberapa fungsi dalam kode Anda.