Subshells Linux Lanjutan dengan contoh

Subshells Linux Lanjutan dengan contoh

Jika anda membaca Subshells Linux sebelumnya untuk pemula dengan artikel Contoh, atau berpengalaman dengan subshells sudah, anda tahu bahawa subshells adalah cara yang kuat untuk memanipulasi perintah bash dalam talian, dan dengan cara sensitif konteks.

Dalam tutorial ini anda akan belajar:

  • Cara membuat arahan subshell yang lebih maju
  • Di mana anda boleh menggunakan subshell yang lebih maju dalam kod anda sendiri
  • Contoh arahan subshell yang lebih maju
Subshells Linux Lanjutan dengan contoh

Keperluan perisian dan konvensyen yang digunakan

Keperluan Perisian dan Konvensyen Talian Perintah Linux
Kategori Keperluan, konvensyen atau versi perisian yang digunakan
Sistem Pengedaran linux-bebas
Perisian Baris perintah bash, sistem berasaskan linux
Yang lain Sebarang utiliti yang tidak termasuk dalam shell bash secara lalai boleh dipasang menggunakan sudo apt-get memasang nama utiliti (atau yum dan bukannya apt-get)
Konvensyen # - memerlukan komando linux untuk dilaksanakan dengan keistimewaan akar sama ada secara langsung sebagai pengguna root atau dengan menggunakan sudo perintah
$-Memerlukan komando linux untuk dilaksanakan sebagai pengguna yang tidak istimewa

Contoh 1: Mengira fail

$ jika [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Kemudian echo "menemui satu atau lebih kejadian fail [a-z]*!"; fi 


Di sini kita mempunyai jika pernyataan dengan sebagai nilai perbandingan pertama subshell. Ini berfungsi dengan baik dan memberikan banyak kelonggaran ketika menulis jika pernyataan. Ia berbeza maka binari (benar atau palsu) seperti operasi contohnya jika grep -q 'search_term' ./docfile.txt penyata. Sebaliknya, ia dinilai per se sebagai perbandingan standard (dipadankan dengan lebih besar-kemudian-sifar -GT 0 fasal).

Subshell cuba fail senarai direktori yang dinamakan [a-z]*, i.e. fail bermula dengan sekurang -kurangnya satu huruf di A-Z julat, diikuti dengan watak berikutnya. Ia adalah kesilapan dengan menambah 2>/dev/null - i.e. Sebarang ralat dipaparkan (dihidupkan stderr - output ralat standard, yang ditandakan oleh 2) akan dialihkan semula > ke /dev/null - i.e. peranti null linux - dan dengan itu tidak diendahkan.

Akhirnya kita lulus input LS ke WC -L yang akan menghitung untuk kita berapa banyak baris (atau dalam kes ini, fail) dilihat. Sekiranya hasilnya lebih dari 0, nota bermaklumat ditunjukkan.

Perhatikan bagaimana konteks di mana subshell beroperasi bervariasi. Pertama, dalam kes ini, Subshell bekerja di dalam direktori kerja semasa (i.e. $ Pwd) yang juga merupakan lalai i.e. subshells secara lalai bermula dengan persekitaran mereka sendiri PWD Tetapkan ke direktori kerja semasa. Kedua, subshell bekerja di dalam konteks an jika penyata.

Tiada output dihasilkan oleh arahan ini, kerana ia dilaksanakan di dalam direktori kosong. Walau bagaimanapun, ambil perhatian bahawa hakikat bahawa tiada output dijana juga bermakna penindasan ralat kami berfungsi. Mari sahkan bahawa:

$ jika [$ (ls [a -z]* | wc -l) -gt 0]; Kemudian echo "menemui satu atau lebih kejadian fail [a-z]*!"; fi ls: tidak dapat mengakses '[a-z]*': tidak ada fail atau direktori sedemikian 

Kita dapat melihat bagaimana menghapus penindasan ralat yang berfungsi dalam contoh terdahulu. Mari kita buat fail dan lihat bagaimana satu-liner kami berfungsi:

$ sentuh $ jika [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Kemudian echo "menemui satu atau lebih kejadian fail [a-z]*!"; Fi menemui satu atau lebih kejadian fail [a-z]*! 


Hebat, ia kelihatan seperti skrip satu-liner kami berfungsi dengan baik. Mari kita tambahkan fail sekunder, dan lihat apakah kita dapat memperbaiki mesej

$ sentuh b $ if [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Kemudian echo "menemui satu atau lebih kejadian fail [a-z]*!"; Fi menemui satu atau lebih kejadian fail [a-z]*! $ jika [$ (ls [a -z]* 2>/dev/null | wc -l) -gt 0]; Kemudian echo "dijumpai tepat $ (ls [a-z]* 2>/dev/null | wc -l) kejadian [a-z]* fail!"; Fi mendapati tepat 2 kejadian [a-z]* fail! 

Di sini kita melihat bahawa menambah fail kedua (oleh sentuh b) tidak membuat perbezaan (seperti yang dilihat pada yang pertama jika perintah), melainkan jika kita menukar output untuk benar -benar melaporkan berapa banyak fail yang dijumpai dengan memasukkan subshell sekunder dalam output.

Walau bagaimanapun, ini tidak dikodkan secara optimum; Dalam kes ini, dua subshells memerlukan pelaksanaan (kos penciptaan subshell sangat minimum, tetapi jika anda mempunyai banyak subshells yang dicipta dalam frekuensi tinggi, kos tidak penting), dan penyenaraian langsung diminta dua kali (menghasilkan tambahan I/O dan melambatkan kod kami ke kelajuan subsistem I/O dan jenis cakera yang digunakan). Mari letakkan ini dalam pemboleh ubah:

$ Count = "$ (ls [a -z]* 2>/dev/null | wc -l)"; jika [$ count -gt 0]; kemudian echo "ditemui tepat $ count kejadian [a-z]* fail!"; Fi mendapati tepat 2 kejadian [a-z]* fail! 

Hebat. Ini adalah kod yang lebih optimum; Subshell tunggal digunakan dan hasilnya disimpan dalam pembolehubah yang kemudiannya digunakan dua kali, dan hanya satu pengambilan penyenaraian direktori cakera tunggal yang diperlukan. Perhatikan juga bahawa penyelesaian ini mungkin lebih selamat benang.

Contohnya, di jika pernyataan yang mempunyai dua subshells, jika pada masa di antara pelaksanaan subshells fail ketiga telah dibuat, hasilnya mungkin kelihatan seperti ini: Dijumpai tepat 3 kejadian fail [a-z]*! sedangkan yang pertama jika pernyataan (menggunakan subshell pertama) benar -benar layak jika 2 -gt 0 - i.e. 2. Ia tidak akan membuat sedikit perbezaan dalam kes ini, tetapi anda dapat melihat bagaimana dalam beberapa pengekodan ini mungkin menjadi sangat penting untuk diperhatikan.

Contoh 2: Subshells untuk pengiraan

$ sentuh z $ echo $ [$ (tarikh + %s) - $ (stat -c %z ./z)] 1 $ echo $ [$ (tarikh + %s) - $ (stat -c %z ./z)] 5 

Di sini kami membuat fail, iaitu z, dan kemudiannya mengetahui umur fail dalam beberapa saat dengan menggunakan arahan kedua. Beberapa saat kemudian, kami melaksanakan arahan lagi dan kami dapat melihat failnya sekarang 5 saat.

The tarikh +%s Perintah memberi kita masa sekarang dalam beberapa saat sejak Epoch (1970-01-01 UTC), dan stat -c %z memberi kita detik sejak zaman untuk fail yang sebelum ini dibuat, dan kini dirujuk di sini sebagai ./z, Oleh itu, semua yang perlu kita lakukan adalah untuk menolak kedua -dua ini antara satu sama lain. Kami meletakkan tarikh +%s pertama kerana ini adalah bilangan tertinggi (masa semasa) dan dengan itu betul mengira offset dalam beberapa saat.

The -c pilihan untuk stat hanya menunjukkan bahawa kami mahukan pemformatan output tertentu, dalam kes ini %Z, atau dengan kata lain masa sejak zaman. Untuk Tarikh sintaks untuk idea yang sama adalah +%s, walaupun berkaitan dengan masa kini dan tidak berkaitan dengan fail tertentu.

Contoh 3: Subshells di dalam SED dan alat lain

$ echo '0'> a $ sed -i "s | 0 | $ (whoami) |" ./A $ CAT A ROEL 


Seperti yang anda lihat, kami boleh menggunakan subshell di hampir mana -mana arahan yang kami laksanakan pada baris arahan.

Dalam kes ini, kami membuat fail a dengan kandungan sebagai 0 dan seterusnya dalam talian menggantikan 0 ke $ (whoami) yang, apabila subshell dilaksanakan sebagai arahan yang dihuraikan, akan menggantikan nama pengguna Roel. Berhati -hati untuk tidak menggunakan petikan tunggal kerana ini akan menjadikan subshell tidak aktif kerana rentetan akan ditafsirkan sebagai teks literal:

$ echo '0'> a $ sed -i 's | 0 | $ (whoami) |' ./A $ CAT A $ (WHOAMI) 

Perhatikan di sini bahawa sed sintaks diaktifkan (S | 0 | ... |) masih berfungsi dengan betul (!), sedangkan fungsi subshell bash $ () tidak!

Contoh 4: Menggunakan Eval dan A untuk Gelung

$ Loops = 3 $ echo 1 ... $ loops 1 ... 3 $ eval echo 1 ... $ loops 1 2 3 $ for i in $ (echo 1 ... $ loops); lakukan echo "$ i"; selesai 1 ... 3 $ untuk i dalam $ (eval echo 1 ... $ loops); lakukan echo "$ i"; dilakukan 1 2 3 

Contoh ini, sementara bukan cara yang optimum untuk melaksanakannya untuk Gelung, menunjukkan kepada kita beberapa cara untuk mengintegrasikan subshells walaupun di dalam gelung. Kami menggunakan eval pernyataan untuk memproses 1 ... 3 teks ke 1 2 3 yang kemudiannya boleh digunakan secara langsung di dalam untuk Klausa berulang gelung.

Kadang-kadang, menggunakan subshells dan membekalkan maklumat dalam-dalam-konteks melalui subshells tidak selalu jelas, dan mungkin memerlukan beberapa ujian, tweaking dan penalaan halus sebelum subshells melaksanakan seperti yang diharapkan. Ini normal dan selaras dengan pengekodan bash biasa.

Kesimpulan

Dalam artikel ini, kami meneroka beberapa contoh yang lebih mendalam dan maju menggunakan Subshells di Bash. Kekuatan Subshells akan membolehkan anda mengubah skrip satu-liner yang paling banyak ke versi yang lebih kuat, belum lagi kemungkinan menggunakannya di dalam skrip anda. Apabila anda mula meneroka subshells dan cari beberapa cara yang bagus untuk menggunakannya, sila hantar mereka di bawah dalam komen!

Nikmati!

Tutorial Linux Berkaitan:

  • Perkara yang hendak dipasang di Ubuntu 20.04
  • Perkara yang perlu dilakukan setelah memasang ubuntu 20.04 Focal Fossa Linux
  • Subshells Linux untuk pemula dengan contoh
  • Pengenalan kepada Automasi, Alat dan Teknik Linux
  • Cara Menggunakan Subshells Bash Di dalam Jika Kenyataan
  • Perkara yang perlu dilakukan setelah memasang Ubuntu 22.04 Jur -ubur Jammy ..
  • Perintah Linux: Top 20 Perintah Paling Penting yang Anda Perlu ..
  • Perintah Linux Asas
  • Muat turun linux
  • Pasang Arch Linux di Workstation VMware