Tại sao bash biến mở rộng giữ lại dấu ngoặc kép?


12
> echo "hi"
hi
> VAR='echo "hi"'
> $VAR
"hi"

Tại sao đầu ra của các lệnh trên lại khác nhau?

Một điều tương tự xảy ra với dấu ngoặc đơn:

> VAR="echo 'hi'"
> $VAR
> 'hi'

6
Xin đừng có thói quen nhúng các đoạn mã thực thi trong các biến. Điều này có xu hướng khó khăn nhấtevallà một mỏ của các lỗ hổng bảo mật tiềm năng mà bạn phải bước đi rất cẩn thận
jw013

@ jw013 Điểm tốt và bài viết tuyệt vời. Tôi thích câu trích dẫn "Biến giữ dữ liệu, hàm giữ mã." từ liên kết đầu tiên, nhưng đối với việc sử dụng của tôi, dữ liệu được cung cấp cho một hàm (trong trường hợp này at) mã. Bất kỳ lời khuyên về một cách an toàn hơn để tổ chức / thu thập mã sẽ được đưa ra at?
Cory Klein

atlấy shcú pháp làm đầu vào. Do đó, tạo đầu vào cho atphương tiện tạo ra shcú pháp được trích dẫn hợp lệ từ đầu vào tùy ý, không tầm thường, vì vậy tôi cố gắng tránh nó nếu có thể. Nó thực sự có ích nếu bạn có thể cung cấp thêm một chút chi tiết về những gì bạn đang cố gắng thực hiện.
jw013

Xin lỗi, tôi không muốn làm sao lãng quá nhiều chi tiết, nhưng những gì tôi đang làm không thực sự phức tạp, IMO. Tôi đang tạo một tập lệnh mất "thời gian" và "thông điệp". Sau đó nó chạy attrong "thời gian" nhất định và bảo atchạy lệnh dzen2. dzen2lấy "thông điệp" từ stdin và cũng sử dụng một số tham số tĩnh khác. Khó khăn là tôi cần chuyển tham số "tin nhắn" từ người dùng vào dzen2lệnh, nhưng tôi không thực sự dzen2tự chạy , tôi đang nói atđể làm điều đó.
Cory Klein

Câu trả lời:


16

Các cặp trích dẫn thêm sẽ chỉ được sử dụng bởi một bước đánh giá thêm. Ví dụ: bị ép buộc bởi eval:

bash-4.2$ VAR='echo "hi"'

bash-4.2$ $VAR
"hi"

bash-4.2$ eval $VAR
hi

Nhưng nói chung là một ý tưởng tồi để đặt các lệnh với các tham số trong một chuỗi. Sử dụng một mảng thay thế:

bash-4.2$ VAR=(echo "hi")

bash-4.2$ "${VAR[@]}"
hi

1
Cũng cần lưu ý rằng các trích dẫn được đánh giá khác nhau; dấu ngoặc kép (") cho phép đánh giá chuỗi kèm theo, dấu ngoặc đơn (') in chuỗi dưới dạng chữ. Ví dụ: "$(ls)"'$(ls)'. Đây là lý do tại sao dấu ngoặc kép xuất hiện trong các ví dụ câu hỏi ban đầu.
Joseph Kern

Một mảng cũng là một nguồn của vấn đề. Mã thuộc về chức năng, dữ liệu cho các biến. Ví dụ bạn trình bày chỉ hoạt động vì các trích dẫn được loại bỏ trong phần tách của mảng. A printf '<%s> ' "${VAR[@]}"sẽ cho thấy rằng trích dẫn đã được gỡ bỏ. Nếu bạn đặt VAR là VAR=(echo \"hi\")thực sự có dấu ngoặc kép, vấn đề tương tự lại xuất hiện, $ ${VAR[@]}sẽ in"hi"

9

Trích dẫn loại bỏ chỉ xảy ra trên các từ đầu vào ban đầu, không phải trên kết quả của việc mở rộng. Báo giá là một phần của các biến mở rộng không được chạm tới.


2

Nếu bạn lùi lại một chút, bạn có thể thấy tại sao thay thế hoàn toàn nên giữ lại dấu ngoặc kép.

Điểm của các trích dẫn trong hệ vỏ Unix / Linux / BSD là giữ các phần của một chuỗi có thể được phân tách thành nhiều chuỗi. Vì theo mặc định, shell sử dụng khoảng trắng làm dấu tách mã thông báo, một chuỗi có khoảng trắng (như "một hai ba") nếu không được trích dẫn hoặc thoát bằng cách nào đó, sẽ được phân tách thành 3 chuỗi: "một", "hai" và "ba".

Nếu một lập trình viên muốn một chuỗi có giá trị của một số biến được nội suy:

VAR=two
STRING="one $VAR three"

Shell hoàn toàn không nên xóa dấu ngoặc kép: chuỗi chứa khoảng trắng sẽ được phân tách thành 3 chuỗi nhỏ hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.