Vấn đề đó rất cụ thể bash
, và đó là vì họ đã quyết định bash
tách phần mở rộng dấu ngoặc ra khỏi phần mở rộng tên tệp (globalbing) và để thực hiện trước, trước tất cả các bản mở rộng khác.
Từ bash
trang hướng dẫn:
Thứ tự mở rộng là: mở rộng cú đúp; mở rộng dấu ngã, mở rộng tham số và biến, mở rộng số học và thay thế lệnh (được thực hiện theo kiểu từ trái sang phải); tách từ; và mở rộng tên đường dẫn.
Trong ví dụ của bạn, bash
sẽ chỉ thấy niềng răng của bạn sau khi nó đã thực hiện thay thế lệnh (the $(echo ...)
), khi quá muộn.
Điều này khác với tất cả các shell khác, thực hiện việc mở rộng dấu ngoặc ngay trước đó (và một số thậm chí là một phần của) mở rộng tên đường dẫn (globalbing). Điều đó bao gồm nhưng không giới hạn csh
ở nơi mở rộng cú đúp được phát minh lần đầu tiên.
$ csh -c 'ls `echo "test{1,2}.txt"`'
test1.txt test2.txt
$ ksh -c 'ls $(echo "test{1,2}.txt")'
test1.txt test2.txt
$ var=nope var1=one var2=two bash -c 'echo $var{1,2}'
one two
$ var=nope var1=one var2=two csh -c 'echo $var{1,2}'
nope1 nope2
Ví dụ thứ hai là trong cùng csh
, zsh
, ksh93
, mksh
hoặc fish
.
Ngoài ra, lưu ý rằng mở rộng dấu ngoặc như là một phần của Globing cũng có sẵn thông qua glob(3)
chức năng thư viện (ít nhất là trên Linux và tất cả các BSD), và trong các triển khai độc lập khác (ví dụ: trong perl perl -le 'print join " ", <test{1,2}.txt>'
:).
Tại sao điều đó được thực hiện khác đi bash
có lẽ là một câu chuyện đằng sau nó, nhưng FWIW tôi không thể tìm thấy bất kỳ lời giải thích hợp lý nào, và tôi thấy tất cả các hợp lý hóa hậu-hoc không thuyết phục.