Perluasan variabel shell dan efek glob dan dibagi di atasnya

18

Posting ini sebenarnya mengandung dua pertanyaan terpisah tetapi saya pikir pengelompokan bersama akan memberikan lebih banyak konteks. Saya telah melalui pertanyaan ini tentang tanda kutip di sekitar variabel tapi saya tidak begitu mengerti apa arti ekspansi variabel di tempat pertama. Jadi pertanyaan pertama saya adalah:

  1. Apa yang dimaksud dengan ekspansi variabel di bicara unix / linux?

Bagian kedua dari pertanyaan saya terkait dengan persyaratan berikut:

  1. gumpal
  2. membagi

Apa arti hal di atas dan bagaimana pengaruhnya terhadap ekspansi variabel? Jawaban untuk pertanyaan awal menyebutkan sebagai berikut:

Pikirkan tentang tidak adanya tanda kutip (dalam konteks daftar) sebagai operator split + glob.

Seolah echo $ test adalah echo glob (split ("$ test")).

Saya tidak dapat menemukan jawaban yang secara langsung membahas konsep globbing dan splitting, melainkan menggunakan istilah-istilah itu secara langsung dalam menjawab pertanyaan-pertanyaan lain seperti yang baru-baru ini .

Kutu buku
sumber

Jawaban:

15

Ekspansi variabel (istilah standarnya adalah ekspansi parameter , dan kadang-kadang disebut juga subtitusi variabel ) pada dasarnya berarti mengganti variabel dengan nilainya. Lebih tepatnya, itu berarti mengganti $VARIABLEkonstruk (atau ${VARIABLE}atau ${VARIABLE#TEXT}konstruk lain) dengan beberapa teks lain yang dibangun dari nilai variabel. Teks lain ini adalah perluasan dari variabel.

Proses ekspansi berjalan sebagai berikut. (Saya hanya membahas kasus umum, beberapa pengaturan dan ekstensi shell memodifikasi perilaku.)

  1. Ambil nilai variabel, yang merupakan string. Jika variabel tidak ditentukan, gunakan string kosong.
  2. Jika konstruk mencakup transformasi, terapkan. Misalnya, jika konstruknya adalah ${VARIABLE#TEXT}, dan nilai variabel dimulai dengan TEXT, hapus TEXTdari awal nilai.
  3. Jika konteksnya meminta satu kata (misalnya dalam tanda kutip ganda, atau di sisi kanan penugasan, atau di dalam dokumen di sini), berhenti di sini. Kalau tidak, lanjutkan dengan langkah selanjutnya.
  4. Membagi nilai menjadi kata-kata terpisah di setiap urutan spasi putih. (Variabel IFSdapat diubah untuk dipisah pada karakter selain spasi putih.) Dengan demikian hasilnya bukan lagi string, tetapi daftar string. Daftar ini bisa kosong jika nilai hanya berisi spasi putih.
  5. Perlakukan setiap elemen dari daftar sebagai pola wildcard nama file, yaitu glob . Jika pola cocok dengan beberapa file, itu diganti dengan daftar nama file yang cocok, jika tidak dibiarkan sendiri.

Misalnya, anggap bahwa variabel fooberisi a* b* c*dan direktori saat ini berisi file bar, bazdan paz. Kemudian ${foo#??}diperluas sebagai berikut:

  1. Nilai variabel adalah string 8 karakter a* b* c*.
  2. #??berarti melepaskan dua karakter pertama, menghasilkan string 6 karakter  b* c*(dengan spasi awal).
  3. Jika ekspansi dalam konteks daftar (yaitu tidak dalam tanda kutip ganda atau konteks serupa lainnya), lanjutkan.
  4. Pisahkan string menjadi kata-kata yang dibatasi spasi, menghasilkan daftar dua-string: b*dan c*.
  5. String b*, yang ditafsirkan sebagai pola, cocok dengan dua file: bardan baz. String c*tidak cocok dengan file sehingga dibiarkan sendiri. Hasilnya adalah daftar tiga senar: bar, baz, c*.

Misalnya echo ${foo#??}mencetak bar baz c*(perintah echobergabung argumennya dengan spasi di antaranya).

Untuk detail lebih lanjut, lihat:

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Perhatikan bahwa itu disebut ekspansi parameter karena berlaku untuk variabel ( $var) dan jenis lain dari parameter seperti $1, $#, $?, $-...
Stéphane Chazelas
12

gumpalan / split

Saya akan mengambil glob / split dulu. @ Stephane menjawab Anda terhubung dengan menggunakan istilah-istilah itu dalam pengertian umum. Itu bukan perintah aktual atau semacamnya, hanya operasi semu.

Itu split("$test")akan membagi konten "$ test" menjadi "array" elemen.

The glob(...)kemudian akan mengurus untuk memperluas setiap elemen ini yang mengandung shell globbing karakter seperti *atau rentang [1-2].

Contoh

Katakan string kita $testadalah sebagai berikut.

$ test="afile[1-2] afile[3-5]"

Juga katakanlah kita memiliki direktori dengan beberapa file di dalamnya.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Sekarang jika kami mencoba untuk menggemakannya tanpa tanda kutip, Anda harus memperhatikan bahwa string kami terpecah pada spasi, dan kemudian setiap karakter globbing diperluas.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Namun jika kita mengutip variabel ketika kita meneruskannya sebagai argumen untuk echokita akan mendapatkan string literal asli.

$ echo "$test"
afile[1-2] afile[3-5]

ekspansi variabel

Istilah ekspansi variabel dimaksudkan untuk mencakup operasi dasar yang dilakukan shell sebagai bagian dari operasi dasar itu. Shell bertanggung jawab atas penguraian input dan kemudian mengeksekusi input ini setelah dianggap benar secara sintaksis.

Dalam contoh kita sebelumnya. Ketika variabel $testdisajikan untuk echodikutip, kami memberi tahu shell untuk terus maju dan membagi argumen itu dan kemudian menggumpalnya.

Ketika dikutip, kami pada dasarnya menonaktifkan fitur itu dengan variabel apa pun yang kami bungkus dengan tanda kutip ganda.

Contoh

Berikut adalah beberapa contoh tambahan dari globbing dan splitting.

Glob / perpecahan terjadi secara otomatis

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

Glob / pemisahan dinonaktifkan melalui penawaran ganda

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
slm
sumber
Saya tidak tahu rentang juga bekerja dalam urutan terbalik.
Joe