Lebih
Bagaimana untuk iterate atas argumen di Bash script
Saya memiliki kompleks perintah yang saya'd seperti untuk membuat shell/bash script. Saya bisa menulis ini dalam hal $1
dengan mudah:
foo $1 args -o $1.ext
Aku ingin bisa melewati beberapa masukan nama untuk script. Apa's cara yang tepat untuk melakukannya?
Dan, tentu saja, saya ingin menangani nama file dengan ruang-ruang di dalamnya.
830
6
Gunakan"$@"` untuk mewakili semua argumen:
Ini akan iterate atas setiap argumen dan mencetaknya pada baris terpisah. $@ berperilaku seperti $* kecuali bahwa ketika mengutip argumen yang dipecah dengan baik jika ada ruang di dalamnya:
Rewrite dari sekarang dihapus jawaban oleh VonC. Robert Berjudi's ringkas jawaban yang berhubungan langsung dengan pertanyaan. Yang satu ini menguatkan pada beberapa masalah dengan nama file yang mengandung spasi. Lihat juga: ${1:+"$@"} pada /bin/sh Dasar tesis:
"$@"
benar,$ *
(tanda kutip) hampir selalu salah. Hal ini karena"$@"
bekerja dengan baik ketika argumen yang mengandung spasi, dan bekerja sama sebagai$*
ketika mereka don't. Dalam beberapa keadaan,"$*"
OK juga, tapi"$@"
biasanya (tapi tidak selalu) bekerja di tempat yang sama. Dikutp,$@
dan$*
yang setara (dan hampir selalu salah). Jadi, apa perbedaan antara$*
,$@
,"$*"
, dan"$@"
? Mereka semua yang terkait dengan 'semua argumen ke shell', tetapi mereka melakukan hal yang berbeda. Ketika dikutp,$*
dan$@
melakukan hal yang sama. Mereka memperlakukan setiap 'kata' (urutan non-whitespace) sebagai argumen. Dikutip bentuk yang cukup berbeda, meskipun:"$*"
memperlakukan daftar argumen sebagai satu ruang-string yang dipisahkan, sedangkan"$@"
memperlakukan argumen yang hampir persis seperti mereka ketika ditentukan pada baris perintah."$@"
mengembang untuk apa-apa sama sekali ketika tidak ada argumen posisi;"$*"
memperluas ke string kosong — dan ya, di sana's perbedaan, meskipun hal ini dapat sulit untuk mengartikannya. Lihat informasi lebih lanjut di bawah ini, setelah pengenalan (non-standar) perintahal
. Sekunder tesis: jika anda perlu untuk memproses argumen dengan spasi dan kemudian lulus mereka ke perintah lain, maka anda kadang-kadang perlu non-standar alat-alat untuk membantu. (Atau anda harus menggunakan array, hati-hati:"${array[@]}"
berperilaku analog ke"$@"
.) Contoh:Mengapa doesn't yang bekerja? Itu doesn't bekerja karena proses shell kutipan sebelum mengembang variabel-variabel. Jadi, untuk mendapatkan shell untuk memperhatikan kutipan tertanam di
$var
, anda harus menggunakaneval
:Ini akan benar-benar sulit ketika anda memiliki nama file seperti "`Dia berkata, "Don't melakukan hal ini!"" (dengan tanda kutip dan tanda kutip ganda dan ruang).
Kerang (semua dari mereka) tidak membuatnya sangat mudah untuk menangani barang jadi (lucunya) banyak Unix program tidak melakukan pekerjaan yang baik penanganan mereka. Pada Unix, nama file (satu komponen) dapat berisi karakter apapun kecuali slash dan NUL
'\0'
. Namun, kerang sangat mendorong tidak ada spasi atau baris baru atau tab di mana saja dalam sebuah nama jalan. Hal ini juga mengapa standar Unix nama file tidak boleh mengandung spasi, dll. Ketika berhadapan dengan nama-nama file yang dapat berisi spasi dan lainnya merepotkan karakter, anda harus sangat berhati-hati, dan saya menemukan lama yang lalu bahwa saya membutuhkan sebuah program yang tidak standar di Unix. Saya menyebutnyamelarikan diri
(versi 1.1 tanggal 1989-08-23T16:01:45Z). Berikut adalah contoh darimelarikan diri
di gunakan - dengan SKKL sistem kontrol. Ini adalah cover naskah yang tidak baikdelta
(berpikir check-in) danmendapatkan
(berpikir check-out). Berbagai argumen, terutama-y
(alasan mengapa anda membuat perubahan) akan berisi kosong dan baris baru. Perhatikan bahwa script tanggal dari tahun 1992, sehingga menggunakan back-kutu bukan$(cmd ...)
notasi dan tidak menggunakan#!/bin/sh
pada baris pertama.(Saya mungkin akan tidak menggunakan melarikan diri begitu benar-benar hari ini - itu tidak diperlukan dengan
-e
argumen, misalnya - tapi secara keseluruhan, ini adalah salah satu sederhana menggunakan scriptmelarikan diri
.) Yangmelarikan diri
program hanya output argumen, bukan sepertiecho
tidak, tetapi memastikan bahwa argumen yang dilindungi untuk digunakan denganeval
(satu tingkat darieval
; saya punya sebuah program yang melakukan remote shell eksekusi, dan yang diperlukan untuk melarikan diri output darimelarikan diri
).Saya memiliki program yang disebut
al
yang berisi daftar argumen satu per baris (dan itu bahkan lebih kuno: versi 1.1 tanggal 1987-01-27T14:35:49). Hal ini paling berguna ketika debugging script, karena dapat dihubungkan ke command line untuk melihat argumen apa yang sebenarnya dilewatkan ke perintah.[Ditambahkan: Dan sekarang untuk menunjukkan perbedaan antara berbagai
"$@"
notasi, berikut adalah salah satu contoh lagi:Melihat bahwa tidak ada yang mempertahankan asli kosong antara
*
dan*/*
pada command line. Juga, perhatikan bahwa anda dapat mengubah 'argumen baris perintah' in the shell dengan menggunakan:Ini set 4 pilihan, '
-yang baru
', '-memilih
', 'dan
', dan 'arg dengan ruang
'.] Hmm, yang's cukup lama jawaban mungkin tafsir adalah istilah yang lebih baik. Kode sumber untuk
melarikan diri
tersedia berdasarkan permintaan (email untuk firstname dot lastname at gmail dot com). Kode sumber untukal
adalah sangat sederhana:Yang's semua. Hal ini sama dengan
test.sh
script bahwa Robert Berjudi menunjukkan, dan dapat ditulis sebagai fungsi shell (tapi fungsi shell didn't ada di versi lokal dari Bourne shell ketika saya pertama kali menulisal
). Perhatikan juga bahwa anda dapat menulisal
sebagai sebuah skrip shell sederhana:Bersyarat diperlukan sehingga tidak menghasilkan output ketika lulus tidak ada argumen. The
printf
perintah ini akan menghasilkan sebuah baris kosong dengan hanya format string argumen, tapi program C menghasilkan apa-apa.Perhatikan bahwa Robert's jawaban adalah benar, dan ia bekerja di
sh
juga. Anda dapat (portable) menyederhanakan bahkan lebih jauh:setara dengan:
I. e., anda don't perlu apa-apa!
Pengujian (
$
adalah command prompt):Saya pertama kali membaca tentang hal ini di Unix Lingkungan Pemrograman oleh Kernighan dan Tombak.
Di
bash
,membantu
dokumen ini:Untuk kasus sederhana anda juga dapat menggunakan
shift
. Memperlakukan daftar argumen seperti antrian. Masing-masingshift
melempar argumen pertama keluar dan indeks dari masing-masing argumen yang tersisa adalah decremented.Anda juga dapat mengakses mereka sebagai sebuah elemen array, misalnya jika anda don't ingin untuk iterate melalui semua dari mereka