Hiểu backtick (`)


35

Tôi đang thử lệnh

$ b=5; echo `$b`;
-bash: 5: command not found

nhưng nó không in 5 như dự kiến. Tôi đang thiếu gì ở đây?

`(Backquote / backtick) có nghĩa là gì trong các lệnh? dường như nói rằng `đánh giá các lệnh bên trong và thay thế chúng bằng đầu ra.


8
Lưu ý rằng backticks không được khuyến khích vì bạn sẽ mất khả năng thực hiện thay thế thực thi lồng nhau. Insetad, $ (somecommand) được ưa thích. Imho nó cải thiện khả năng đọc.
Tommy

6
@ Mẹ ơi, Không, backticks có thể được lồng vào nhau, nhưng nó trở thành một cơn ác mộng thoát ra, đặc biệt là khi trích dẫn kép.
Stéphane Chazelas

Câu trả lời:


52

Văn bản giữa các backticks được thực thi và thay thế bằng đầu ra của lệnh (trừ các ký tự dòng mới theo dõi và hãy cẩn thận rằng các hành vi shell thay đổi khi có các ký tự NUL trong đầu ra). Điều đó được gọi là thay thế lệnh bởi vì nó được thay thế bằng đầu ra của lệnh. Vì vậy, nếu bạn muốn in 5, bạn không thể sử dụng backticks, bạn có thể sử dụng dấu ngoặc kép, thích echo "$b"hoặc chỉ bỏ bất kỳ trích dẫn nào và sử dụng echo $b.

Như bạn có thể thấy, vì $bchứa 5, khi sử dụng backticks bashđang cố chạy lệnh 5và vì không có lệnh đó, nó không thành công với thông báo lỗi.

Để hiểu cách backticks hoạt động, hãy thử chạy này:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1nên in dòng đầu tiên của /etc/passwdtập tin. Nhưng vì chúng tôi sử dụng backticks, nó không in cái này trên console. Thay vào đó, nó được lưu trữ trong Abiến. Bạn có thể lặp lại $Ađiều này. Lưu ý rằng cách in dòng đầu tiên hiệu quả hơn là sử dụng lệnh head -n1 /etc/passwdnhưng tôi muốn chỉ ra rằng biểu thức bên trong backticks không phải đơn giản.

Vì vậy, nếu dòng đầu tiên của / etc / passwd là root:x:0:0:root:/root:/bin/bash, lệnh đầu tiên sẽ được thay thế động bằng bash to A="root:x:0:0:root:/root:/bin/bash".

Lưu ý rằng cú pháp này là của vỏ Bourne. Trích dẫn và thoát ra nhanh chóng trở thành một cơn ác mộng với nó đặc biệt là khi bạn bắt đầu lồng chúng. Ksh đã giới thiệu giải $(...)pháp thay thế hiện đã được chuẩn hóa ( POSIX ) và được hỗ trợ bởi tất cả các trình bao (ngay cả trình bao Bourne từ Unix v9). Vì vậy, $(...)ngày nay bạn nên sử dụng thay vì trừ khi bạn cần di chuyển đến các vỏ Bourne rất cũ.

Cũng lưu ý rằng đầu ra của `...`$(...)phải chịu sự phân tách từ và tạo tên tệp giống như mở rộng biến (chỉ trong zsh, chỉ tách từ), do đó, thường sẽ cần được trích dẫn trong ngữ cảnh danh sách.


1
Xin chào @Krzysztof, thật hữu ích! "vì $ b chứa 5, bash đang cố chạy lệnh 5" chính xác là thứ tôi đang tìm kiếm
coolcric

you can use quotation marks, like echo "$b"=> "" có làm gì đặc biệt không? Có vẻ như echo $bsẽ làm việc như là tốt.
Tootsie Rolls

@Anita: Trong dấu ngoặc kép nói chung có một số điều đặc biệt (nó thay đổi cách xử lý các ký tự đặc biệt - đặc biệt là khoảng trắng) nhưng trong trường hợp này, chúng có thể bị loại bỏ mà không gặp nhiều vấn đề. Điều này là do không có ký tự đặc biệt nào được sử dụng và echolệnh không quan tâm đến số lượng đối số mà nó nhận được vì vậy nếu bcó một số khoảng trắng bên trong, nó sẽ nhận được nhiều đối số và vẫn sẽ in chúng. Điều này có thể không phải là trường hợp cho các lệnh khác (đặc biệt là khi biến không được đặt) vì vậy tôi có xu hướng luôn bao quanh các biến với dấu ngoặc kép.
Krzysztof Adamski

sẽ là tốt nếu (POSIX)sẽ là một liên kết đến tiêu chuẩn thực tế.
erikbwork

1
@ erikb85: Ghi chú này không được tôi thêm vào nhưng tôi đã chỉnh sửa nó bằng liên kết như bạn đề xuất :)
Krzysztof Adamski

11

Backtick làm chính xác những gì bạn nói nó làm. Bạn đã đặt một biến thành một số nguyên. Khi bạn đặt biến đó vào trong backticks, bash sẽ cố gắng thực thi nó như một lệnh. Vì nó không phải là một lệnh, bạn nhận được lỗi bạn đã thấy.

Những gì bạn muốn làm chỉ đơn giản là:

$ b=5; echo $b

Để hiểu backticks tốt hơn, so sánh với:

$ b=5; a=`echo $b`; echo $a
  5

8

Đi từng bước dòng của bạn nên giải thích nó.

$ b=5; echo `$b`;
  1. đặt biến bthành 5
  2. đánh giá $b(chạy hiệu quả 5)
  3. echoes đầu ra của đánh giá ở trên.

Vì vậy, có, đầu ra bạn nhận được dự kiến. Bạn đang đánh giá nội dung của một biến, không phải là lệnh thực tế mà bạn nghĩ là bạn. Tất cả mọi thứ bạn đặt bên trong backticks là simplay được đánh giá (chạy) trong một vỏ (phụ) mới.


xin chào @gertvdijk, cảm ơn bài viết của bạn! Tôi đã nghĩ rằng `trả lại bất cứ thứ gì còn lại sau khi đánh giá nội dung của nó. Vì vậy, tôi nghĩ rằng '$ b' sẽ trả lại 5 cho tiếng vang để in nó
coolcric
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.