Saya perhatikan bahwa {
dapat digunakan dalam ekspansi brace:
echo {1..8}
atau dalam pengelompokan perintah:
{ls;echo hi}
Bagaimana bash tahu bedanya?
bash
shell-script
lovespring
sumber
sumber
{
ditafsirkan sebagai daftar perintah jika muncul di awal perintah dan sebagai penjepit ekspansi sebaliknya, tapi saya tidak yakin.{ls;echo hi}
tidak legalbash
. Anda membutuhkan ruang setelah penjepit pembuka dan titik koma sebelum yang ditutup.Jawaban:
Alasan disederhanakan adalah adanya satu karakter: space.
Perluasan Brace tidak memproses spasi (tidak dikutip).
Sebuah
{...}
daftar kebutuhan ruang (un-dikutip).Jawaban yang lebih rinci adalah bagaimana shell mem-parsing baris perintah .
Langkah pertama untuk mem-parsing (mengerti) baris perintah adalah membaginya menjadi beberapa bagian.
Bagian-bagian ini (biasanya disebut kata atau token) dihasilkan dari pembagian baris perintah pada setiap meta-karakter dari tautan :
Meta-karakter: spacetabenter;,<>|dan &.
Setelah dipisah, kata-kata mungkin bertipe (seperti dipahami oleh shell):
LC=ALL ...
LC=ALL echo
LC=ALL echo "hello"
LC=ALL echo "hello" >&2
Ekspansi penjepit
Hanya jika "brace string" (tanpa spasi atau meta-karakter) adalah satu kata (seperti dijelaskan di atas) dan tidak dikutip , itu adalah kandidat untuk "Brace ekspansi". Pemeriksaan lebih lanjut dilakukan pada struktur internal nanti.
Dengan demikian, ini:
{ls,-l}
memenuhi syarat sebagai "ekspansi Brace" menjadils -l
, baik sebagaifirst word
atauargument
(dalam bash, zsh berbeda).Tapi ini tidak akan:
{ls ,-l}
. Bash akan membagi spacedan menguraikan baris sebagai dua kata:{ls
dan,-l}
yang akan memicucommand not found
(argumen,-l}
hilang):Baris Anda:
{ls;echo hi}
tidak akan menjadi "Brace expansion" karena dua meta-karakter ;dan space.Ini akan dipecah menjadi tiga bagian ini:
{ls
perintah baru:echo
hi}
. Memahami bahwa ;pemicu dimulainya perintah baru. Perintah{ls
tidak akan ditemukan, dan perintah berikutnya akan mencetakhi}
:Jika ditempatkan setelah beberapa perintah lain, ia tetap akan memulai perintah baru setelah ;:
Daftar
Salah satu "perintah senyawa" adalah "Brace Daftar" (kata-kata saya):
{ list; }
.Seperti yang Anda lihat, itu didefinisikan dengan spasi dan penutup
;
.Ruang-ruang dan ;diperlukan karena keduanya
{
dan}
" Kata-kata Cadangan ".Dan karenanya, untuk dikenali sebagai kata-kata, harus dikelilingi oleh meta-karakter (hampir selalu:) space.
Seperti dijelaskan pada poin 2 dari halaman yang terhubung
Contoh Anda:
{ls;echo hi}
bukan daftar.Perlu penutupan ;dan satu ruang (setidaknya) setelahnya {. Yang terakhir }ditentukan oleh penutup ;.
Ini daftar
{ ls;echo hi; }
. Dan ini{ ls;echo hi;}
juga (kurang umum digunakan, tetapi valid) (Terima kasih @choroba atas bantuannya).Tetapi sebagai argumen (shell tahu perbedaannya) terhadap suatu perintah, itu memicu kesalahan:
Tapi hati-hati dengan apa yang Anda yakini mengupas shell:
sumber
;
dan}
.{ ls;}
berfungsi sebagai titik koma sudah menjadi meta-karakter.Blok
{
adalah kata kunci shell, sehingga harus dipisahkan dari kata berikutnya dengan spasi, sementara dalam ekspansi brace, tidak boleh ada ruang (jika Anda perlu memperkuat ruang, Anda harus menghindarinya:)echo {\ ,a}{b,c}
.Anda dapat menggunakan ekspansi brace di awal perintah:
Anda tidak dapat menggunakannya untuk memperluas ke blok, karena penguraian perintah pengelompokan terjadi sebelum ekspansi:
sumber
Ia tahu dengan memeriksa sintaks dari baris perintah. Dengan cara yang sama ia tahu bahwa dalam ekspresi
echo echo
, gema pertama harus diperlakukan sebagai perintah dan gema kedua sebagai parameter dari gema pertama.Dalam bash itu sangat sederhana, karena
{ cmd; }
harus memiliki spasi dan titik koma. Namun, misalnya di zsh mereka tidak diperlukan, tetapi masih dengan menganalisis konteks{}
shell dapat mengetahui apa yang harus dilakukan dengan kontennya.Pertimbangkan yang berikut ini:
Keduanya mengembalikan tanggal saat ini, tetapi
kembali
1 2 3
karena shell tahu{}
dalam argumen untuk perintahecho
, jadi harus diperluas.sumber
{
diikuti oleh tanda kutip ruang tidak memulai ekspansi penjepit di bash.{
. Ruang yang tidak dikutip tidak dapat berada di mana saja karena shell membagi seluruh baris perintah pada spasi.Pertama, kata majemuk harus kata dengan sendirinya dan kata pertama dari baris perintah:
Kedua, kawat gigi individu tidak istimewa (seperti yang Anda lihat di atas). Kawat gigi kosong juga tidak istimewa:
Apa pun tanpa koma juga sendiri
Di sinilah aksi dimulai.
Jadi pada dasarnya untuk ekspansi brace untuk memulai, kita perlu satu kata (tidak dipisahkan menjadi bidang di spasi putih), di dalamnya ada setidaknya satu contoh dari
{...}
dalam yang ada setidaknya satu koma.Ini bisa menjadi kata pertama di baris perintah, omong-omong:
sumber