khả năng hiển thị biến bash trong subshell của lệnh thay thế


7

Tôi đang đọc một cuốn sách kịch bản shell Linux và đã tìm thấy cảnh báo sau:

"Thay thế lệnh tạo ra cái được gọi là lớp con để chạy lệnh kèm theo. Lớp con là lớp vỏ con riêng biệt được tạo từ lớp vỏ đang chạy tập lệnh. Do đó, bất kỳ biến nào bạn tạo trong tập lệnh đều không có sẵn cho lệnh của lớp con".

Tôi đã cố gắng tạo một biến trong CLI bash shell hiện tại của tôi và sau đó nhập lớp con để kiểm tra xem tôi có thể in nó trên màn hình hay không. Vì vậy, có, tôi không thể làm điều đó, dường như là theo trích dẫn ở trên. Tuy nhiên, tôi đã chạy đoạn script sau với lệnh thay thế:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans

Và kết quả là:

5.5555

Theo tôi hiểu, nó không nên in giá trị của var vì subshell không thể "nhìn thấy". Tại sao nó xảy ra?


Nhưng bình luận trong cuốn sách nói rằng nó làm. Tôi thậm chí đã bao gồm biến $ BASH_SUBSHELL để in ra thay thế lệnh và nó được in 1 có nghĩa là nó đã tạo ra một nhánh con.
Donatas

3
Cuốn sách của bạn không tốt lắm.
Michael Homer

1
Ít nhất thì câu nói đó không rõ ràng và gây hiểu lầm, và nếu không thì nó hoàn toàn sai, như bạn đã chứng minh trong câu hỏi này.
Michael Homer

1
Thật đáng mừng là tôi phải đoán rằng cuốn sách có nghĩa là "không có sẵn để chuyển nhượng " (với suy nghĩ có nghĩa là "biến" không có sẵn), nhưng đó là một cách nói rất vô ích nếu đó thực sự là những gì họ muốn nói.
Michael Homer

Câu trả lời:


10

Tuyên bố:

Do đó, bất kỳ biến nào bạn tạo trong tập lệnh đều không có sẵn cho lệnh subshell.

là sai. Phạm vi của một biến được xác định trong shell cha là toàn bộ tập lệnh (bao gồm cả các chuỗi con được tạo bằng thay thế lệnh).

Đang chạy:

#!/bin/bash
var=5.5555
ans1=$(echo $var)
ans2=$(var=6; echo $var)
echo $ans1
echo $ans2

sẽ cho kết quả:

5.5555
6

$var được giải quyết bởi subshell:

  • nếu không có biến cục bộ nào được chỉ định, giá trị của ba biến toàn cục được sử dụng
  • nếu một biến cục bộ được chỉ định, nó sử dụng giá trị của nó

Xem thêm ví dụ 21-2 .


10

Các tuyên bố như được trích dẫn là không đúng sự thật. Điều này cũng không đúng khi biến đã được thay thế trước khi lớp con chạy.

Bạn có thể xác nhận điều này trực tiếp bằng cách sử dụng biến đổi :

$ x=hello
$ echo Result is $(y=x ; echo ${!y} ; echo world)
Result is hello world

Biến xchắc chắn có sẵn trực tiếp cho lớp con (thay vì đã mở rộng giá trị trước đó) bởi vì ${!y}đọc từ biến có tên được lưu trữ y- không tồn tại tại thời điểm lớp con được tạo.


Một cách đọc từ thiện về đoạn văn trong cuốn sách sẽ có nghĩa là nó nói rằng "biến" không có sẵn bởi vì bạn không thể sửa đổi giá trị của nó liên tục. Bất kỳ phép gán biến nào bạn thực hiện trong một lớp con không có sẵn cho vỏ cha mẹ sau đó, cho dù đó là tạo biến mới (như y) hoặc gán giá trị thay thế cho các biến hiện có. Nếu lớp con được gán cho x, giá trị mới sẽ có hiệu lực bên trong lớp con, nhưng đọc từ nó sau đó sẽ cho giá trị ban đầu:

$ x=world
$ echo $(x=hello ; echo $x)
hello
$ echo $x
world

Đó không phải là một cách rất rõ ràng để thể hiện điều đó, ít nhất là trong đoạn bạn đã trích dẫn. Nếu toàn bộ cuốn sách là như vậy, bạn có thể tìm thấy một cuốn tốt hơn (hoặc đọc câu hỏi ở đây thay thế).

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.