Bất kỳ cấu trúc lồng nhau nào có thể được nội suy bên trong các chuỗi có thể có thêm các chuỗi bên trong chúng: chúng được phân tích cú pháp như một tập lệnh mới, cho đến điểm đánh dấu đóng và thậm chí có thể được lồng sâu nhiều cấp. Tất cả thanh một trong những bắt đầu với một $
. Tất cả chúng đều được ghi lại trong tài liệu kết hợp giữa hướng dẫn sử dụng Bash và đặc tả ngôn ngữ lệnh shell POSIX.
Có một vài trường hợp của các cấu trúc này:
Thay thế lệnh bằng$( ... )
, như bạn đã tìm thấy. POSIX chỉ định hành vi này :
Với $(command)
biểu mẫu, tất cả các ký tự theo dấu ngoặc đơn mở cho dấu ngoặc đơn đóng phù hợp sẽ tạo thành lệnh. Bất kỳ tập lệnh shell hợp lệ nào cũng có thể được sử dụng cho lệnh ...
Trích dẫn là một phần của tập lệnh shell hợp lệ, vì vậy chúng được cho phép với ý nghĩa thông thường của chúng.
- Thay thế lệnh bằng cách sử dụng
`
, quá.
Phần tử "từ" của các trường hợp thay thế tham số nâng cao như${parameter:-word}
. Các định nghĩa của "từ" là :
Một chuỗi các ký tự được coi là một đơn vị của vỏ
- bao gồm văn bản được trích dẫn và thậm chí cả trích dẫn hỗn hợp a"b"c'd'e
- mặc dù hành vi thực tế của việc mở rộng là một chút tự do hơn thế, và ví dụ ${x:-hello world}
cũng hoạt động.
Mở rộng số học với $(( ... ))
, mặc dù phần lớn là vô dụng ở đó (nhưng bạn cũng có thể lồng thay thế lệnh hoặc mở rộng biến, và sau đó có các trích dẫn hữu ích bên trong chúng). POSIX nói rằng :
Biểu thức phải được xử lý như thể nó nằm trong dấu ngoặc kép, ngoại trừ trích dẫn kép bên trong biểu thức không được xử lý đặc biệt. Shell sẽ mở rộng tất cả các mã thông báo trong biểu thức để mở rộng tham số, thay thế lệnh và xóa trích dẫn.
vì vậy hành vi này được yêu cầu rõ ràng. Điều đó có nghĩa là echo "abc $((4 "*" 5))"
số học, thay vì toàn cầu.
Lưu ý rằng mặc dù $[ ... ]
mở rộng số học kiểu cũ không được xử lý theo cùng một cách: dấu ngoặc kép sẽ là một lỗi nếu chúng xuất hiện, bất kể việc mở rộng có được trích dẫn hay không. Hình thức này không còn được ghi nhận nữa và dù sao cũng không được sử dụng.
- Bản dịch cụ thể theo địa phương với
$"..."
, thực sự sử dụng "
như là một yếu tố cốt lõi. $"
được coi là một đơn vị duy nhất.
Có một trường hợp lồng nhau nữa mà bạn có thể không mong đợi, không liên quan đến dấu ngoặc kép, đó là mở rộng cú đúp : {a,b{c,d},e}
mở rộng thành "a bc bd e". ${x:-a{b,c}d}
thực hiện không tổ, tuy nhiên; nó được coi là sự thay thế tham số cho " a{b,c
", theo sau là " d}
". Điều đó cũng được ghi lại :
Khi sử dụng dấu ngoặc nhọn, dấu ngoặc kết thúc khớp là '}' đầu tiên không được thoát bằng dấu gạch chéo ngược hoặc trong chuỗi được trích dẫn và không nằm trong phần mở rộng số học được nhúng, thay thế lệnh hoặc mở rộng tham số.
Theo nguyên tắc chung, tất cả các cấu trúc phân định phân tách cơ thể của chúng độc lập với bối cảnh xung quanh (và các trường hợp ngoại lệ được coi là lỗi ). Về bản chất, khi nhìn thấy $(
mã thay thế lệnh, chỉ yêu cầu trình phân tích cú pháp tiêu thụ những gì nó có thể từ cơ thể như thể đó là một chương trình mới, và sau đó kiểm tra xem dấu chấm dứt dự kiến (không thoát )
hoặc ))
hoặc }
) xuất hiện khi trình phân tích cú pháp phụ chạy trong số những thứ nó có thể tiêu thụ.
Nếu bạn nghĩ về chức năng của một trình phân tích cú pháp gốc đệ quy , đó chỉ là một đệ quy đơn giản cho trường hợp cơ sở. Cách thực sự dễ thực hiện hơn so với cách khác, một khi bạn đã có nội suy chuỗi. Bất kể kỹ thuật phân tích cú pháp cơ bản, các shell hỗ trợ các cấu trúc này đều cho kết quả tương tự.
Bạn có thể lồng trích dẫn sâu như bạn muốn thông qua các cấu trúc này và nó sẽ hoạt động như mong đợi. Không nơi nào sẽ bị lẫn lộn khi nhìn thấy một trích dẫn ở giữa; thay vào đó, đó sẽ là sự khởi đầu của một chuỗi trích dẫn mới trong bối cảnh bên trong.