Nó có nghĩa là gì trong shell khi chúng ta đặt một lệnh bên trong ký hiệu đô la và dấu ngoặc đơn: $ (lệnh)


110

Tôi chỉ muốn hiểu dòng mã sau trong shell. Nó được sử dụng để lấy thư mục làm việc hiện tại. Tôi biết rằng $(variable)tên trả về giá trị bên trong tên biến, nhưng những gì được $(command)cho là trả về? Nó có trả về giá trị sau khi thực hiện lệnh không? Trong trường hợp đó, chúng ta có thể sử dụng `để thực hiện lệnh.

CWD="$(cd "$(dirname $0)"; pwd)"

Đầu ra tương tự có thể được lấy từ dòng mã sau cũng trong phiên bản shell khác

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Tôi không thể hiểu ý nghĩa của $(cd..$(dirname.

Ai có thể giúp tôi tìm ra cách lệnh này được thực thi?


1
Và đây là một câu hỏi về những ưu điểm / nhược điểm của $()vs ``: stackoverflow.com/questions/9449778/...
Không

Câu trả lời:


115

Việc sử dụng $tương tự ${HOME}cho giá trị của HOME. Cách sử dụng $tương tự $(echo foo)có nghĩa là chạy bất cứ thứ gì bên trong dấu ngoặc đơn trong một vỏ con và trả về giá trị đó. Trong ví dụ của tôi, bạn sẽ hiểu fooechosẽ viết footheo tiêu chuẩn


37
Đúng; $(...)là một cách viết lệnh tốt hơn là cố gắng sử dụng dấu ngoặc kép. Cân nhắc viết: gcclib=$(dirname $(dirname $(which gcc)))/libsử dụng dấu ngoặc kép. Ngay cả trước khi bạn gặp khó khăn khi thực hiện nó trong Markdown, nó còn khó hơn vì bạn phải thoát khỏi các dấu ngoặc kép của các lệnh lồng nhau, trong khi bạn không làm như vậy với $(...)ký hiệu.
Jonathan Leffler

7
Về mặt kỹ thuật, $(echo foo)tạo ra một lệnh thay thế, không phải một vỏ con. Câu trả lời hiện tại khác đúng. Tôi nghĩ rằng thay thế lệnh được chạy trong một lớp vỏ thay thế, nhưng chúng vẫn là những khái niệm khác nhau.
chạy thận

4
@trysis - thay thế lệnh chắc chắn chạy trong một vỏ con , vì vậy cần lưu ý điều đó.
Eliran Malka

2
Tôi hiểu rằng các thanh backticks tạo ra kết quả giống như $ (), nhưng sự khác biệt có phải hoàn toàn là mỹ phẩm không? có lý do gì để sử dụng cái này so với cái kia, ngoài việc $ () dễ đọc hơn?
Mitchell Tracy,

2
"Việc sử dụng $ like $ (echo foo) có nghĩa là chạy bất cứ thứ gì bên trong dấu ngoặc đơn trong một vỏ con và trả về giá trị đó." ... Điều này thật khó hiểu, vì lệnh $(echo foo)này sẽ cố gắng chạy những gì được trả về từ dấu ngoặc đơn, đầu tiên nó sẽ chạy echo foosau đó sẽ cố chạy foomà báo lỗi
Kế toán م

21
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Ai có thể giúp tôi tìm ra cách lệnh này được thực thi?

Hãy xem xét các phần khác nhau của lệnh. BASH_SOURCElà một biến mảng bash chứa các tên tệp nguồn. Vì vậy, "${BASH_SOURCE[0]}"sẽ trả lại cho bạn tên của tệp script.

dirnamelà một tiện ích do GNU coreutils cung cấp để loại bỏ thành phần cuối cùng khỏi tên tệp. Vì vậy, nếu bạn thực thi tập lệnh của mình bằng cách nói bash foo, "$( dirname "${BASH_SOURCE[0]}" )"sẽ trả về .. Nếu bạn nói bash ../foo, nó sẽ trở lại ..; vì bash /some/path/foonó sẽ trở lại /some/path.

Cuối cùng, toàn bộ lệnh "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"nhận được thư mục tuyệt đối chứa tập lệnh đang được gọi.

$(...) cho phép thay thế lệnh, tức là cho phép đầu ra của một lệnh thay thế chính lệnh đó và có thể lồng vào nhau.


1
Xin lỗi vì đã đến muộn 3 năm, nhưng bạn có thể vui lòng giải thích lý do tại sao tuyên bố có hiệu quả không? Bạn cho biết dirnametrả về đường dẫn của tệp được thực thi (tương đối hoặc tuyệt đối với thư mục làm việc hiện tại), cdthay đổi pwd thành thư mục đó và pwdin ra đường dẫn tuyệt đối của thư mục làm việc hiện tại. Nhưng tại sao họ được tham gia bởi &&? Và điều gì sẽ DIRgiữ lại nếu cdthất bại?
Christian

2
@Christian, &&ngăn không cho pwdchạy nếu cdkhông thành công, như vậy DIRsẽ trống hơn là có một thư mục không chính xác.
Charles Duffy
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.