Biến dạng này là gì = $ (Hoài)


9

Cai tiêp theo nghia la gi:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

Tôi đặc biệt quan tâm đến phần này:

varible=$(...)

Tôi biết rằng dấu ngoặc đơn được sử dụng để thực thi một quy trình con, nhưng nếu chúng được sử dụng cùng với $thì sao?


3
Nếu bạn đang sử dụng bash: Hãy xem trang man thông qua man bashvà tìm kiếm thay thế Lệnh
FloHe

Câu trả lời:


16

Từ hướng dẫn Bash ( man bash):

   Bộ chỉ huy thay thế
       Thay thế lệnh cho phép đầu ra của một lệnh để thay thế
       tên lệnh. Có hai hình thức:

              $ (lệnh)
       hoặc là
              `lệnh`

       Bash thực hiện việc mở rộng bằng cách thực hiện lệnh trong một lớp con
       môi trường và thay thế lệnh thay thế bằng tiêu chuẩn
       đầu ra của lệnh, với bất kỳ dòng mới nào bị xóa. Nhúng
       dòng mới không bị xóa, nhưng chúng có thể bị xóa trong từ
       chia tách. Lệnh thay thế $ (tệp cat) có thể được thay thế bằng
       tương đương nhưng nhanh hơn $ (<file).

(Điều này đúng cho tất cả Bourne giống như vỏ, tức là sh, ksh, zsh, bashvv, và zshcũng có thể dữ liệu chụp với các nhân vật NUL nhúng theo cách này)

Lệnh

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

sẽ gán tên của thư mục chứa tập lệnh (đồng thời thay đổi tất cả dấu gạch chéo ngược thành dấu gạch chéo về phía trước) cho biến basedir. Bất kỳ lỗi, cảnh báo hoặc thông báo chẩn đoán nào khác được đưa ra luồng lỗi tiêu chuẩn sẽ vẫn được hiển thị trên thiết bị đầu cuối ( $(...)chỉ chụp đầu ra tiêu chuẩn của lệnh).

Shell sẽ bắt đầu bằng cách thực hiện thay thế lệnh trong cùng:

echo "$0" | sed -e 's,\\,/,g'

Đầu ra của chuỗi đó sẽ được cung cấp dưới dạng một chuỗi dirnamevà đầu ra của chuỗi đó sẽ được gán cho biến basedir.

Có hai dấu ngoặc kép để đảm bảo rằng sẽ không có phân tách từ hoặc tên tệp nào được thực hiện, nếu không bạn có thể thấy rằng tập lệnh thất bại hoặc tạo đầu ra lạ khi $0(tên của tập lệnh bao gồm đường dẫn được sử dụng để thực thi nó) chứa một khoảng trắng ký tự hoặc một tên tập tin ký tự (chẳng hạn như ?hoặc *).

Nói chung, nên luôn luôn trích dẫn mở rộng (mở rộng biến, thay thế lệnh và mở rộng số học). Xem câu hỏi này và câu trả lời của nó cho một lời giải thích tuyệt vời về lý do tại sao đây là một ý tưởng tốt.

Nếu tập lệnh được thực thi như

$ /usr/local/bin/script.sh

sau đó basedirsẽ nhận được giá trị của /usr/local/bin.

Hoặc, trên Cygwin:

$ bash c:\\Users\\Me\\script.sh

sau đó basedirsẽ nhận được giá trị của c:/Users/Me. Dấu gạch chéo kép trên dòng lệnh trong trường hợp này chỉ là để thoát khỏi dấu gạch chéo ngược đơn từ trình bao. Giá trị thực tế của $0c:\Users\Me\script.sh.

Một cách khác để làm điều tương tự mà không sử dụng dirname, echosedsẽ là

basedir="${0//\\//}"
basedir="${basedir%/*}"

cảm ơn, vì vậy về cơ bản nó bắt đầu phân tích cú pháp từ dấu ngoặc đơn trong cùng, đúng không? và tại sao các trích dẫn được sử dụng?
Maxim Koretskyi

@Maximus Đúng. Tôi đã cập nhật câu trả lời của tôi với thông tin thêm.
Kusalananda

Có lẽ bạn nên nói "đúng với tất cả các vỏ giống như Bourne".

@Serg, lưu ý rằng vỏ Bourne (như /bin/shcủa Solaris 10 trở về trước) không hỗ trợ $(...).
Stéphane Chazelas

@ StéphaneChazelas Tôi sẽ kết hợp điều này.
Kusalananda

6

Nó có nghĩa là để chạy những gì nằm bên trong dấu ngoặc đơn trong một subshelltrở lại đó như là một giá trị , trong trường hợp bạn gán đó varible.


5

Các varible=$(..)gọi thay thế lệnh và nó có nghĩa là không có gì hơn, nhưng để chạy một lệnh shell và lưu trữ sản lượng của nó cho một biến hoặc hiển thị trở lại sử dụng tiếng vang lệnh. Ví dụ: hiển thị ngày và giờ:

echo "Today is $(date)"

và để lưu nó vào một biến:

SERVERNAME=$(hostname)

Để biết thêm thông tin: https://www.cyberciti.biz/faq/unix-linux-bsd-appleosx-bash-assign-variable-command-output/

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.