Sự khác biệt giữa mở rộng và thay thế trong thuật ngữ kịch bản shell


8

Mở rộngthay thế dường như là sự thay thế cho nhau trong cùng một bối cảnh trong ngôn ngữ lập trình shell. Ví dụ: một số tài liệu như hướng dẫn tham khảo Bash , Bash Hackers Wiki sử dụng từ 'mở rộng' để giải thích ' mở rộng tham số shell '. Tuy nhiên, một số tài liệu khác dường như thích từ 'thay thế'. Nâng cao Bash-Scripting Guide sử dụng tham số substituion .

Có sự khác biệt nào giữa 'mở rộng' và 'thay thế' về thuật ngữ lập trình shell không?


Cả hai đều hợp lệ trong các bối cảnh khác nhau, ví dụ variable expansion, command substitution. Nghi ngờ của bạn là gì?
devnull

Không có bối cảnh cụ thể, tôi sợ rằng điều này quá rộngkhông rõ ràng .
devnull

Nhìn vào trang bash man, nói chung, từ "mở rộng" dường như được sử dụng nếu chỉ có nội dung shell-shell, trong khi "thay thế" dường như được ưa thích hơn cho những thứ liên quan đến các quy trình bên ngoài.
celtschk

Nếu bạn nghe theo lời khuyên của tôi, bạn sẽ bỏ đọc những tài liệu đó cho đến khi bạn hoàn toàn quen thuộc với những điều này: pubs.opengroup.org/onlinepub/9699919799/utilities/ trộm Khi bạn hoàn thành những việc bạn làm man shman set. Và khi bạn đã có được những thứ đó, thì bạn sẽ làm các tài liệu dành riêng cho trình bao.
mikeerv

@devnull Bạn nói đúng. Mặc dù tôi đặt liên kết cho bối cảnh, nhưng sẽ tốt hơn nếu chỉ định rõ ràng bối cảnh với câu hỏi. Tôi sẽ chỉnh sửa câu hỏi để mọi người có thể hiểu rõ ràng.
MS.Kim

Câu trả lời:


6

Thay thế gần như đồng nghĩa với việc mở rộng trong bối cảnh này vì ý nghĩa của chúng trùng lặp. Không phải là một danh mục con hoàn chỉnh của cái khác, mặc dù trong phần GNU Manual bạn tham chiếu có những sự thay thế được coi là một phần của việc mở rộng tổng thể.

Một mở rộng đang trích xuất giá trị của một định danh. Ví dụ, nếu this=that, khi chúng tôi mở rộng, thischúng tôi nhận được that. Một mở rộng không liên quan đến sự thay thế được xác định trước ở chỗ giá trị được sử dụng đã tồn tại và đơn giản phải được truy xuất, mặc dù điều này bao gồm kết hợp các giá trị được truy xuất / rõ ràng (chẳng hạn như "mở rộng số học").

Một sự thay thế tạo ra một giá trị là kết quả của một hoạt động đầu vào / đầu ra rõ ràng. Ví dụ, nếu this=$(foo bar), thislà kết quả của việc thực hiện foo barvà nắm bắt đầu ra của nó. 1 Mặc dù giá trị do thay thế có thể hoàn toàn có thể dự đoán được, nó khác với giá trị được lấy trong một bản mở rộng thông thường vì nó không thực sự tồn tại cho đến khi sự thay thế diễn ra - nó được tạo ra.

Sự thay thế có hai hương vị, mệnh lệnhquy trình , đó là loại đối xứng:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

"Lệnh" trong cái đầu tiên là ls, "quá trình" trong cái thứ hai. Chúng tôi có thể nói những gì đang được thay thế thực sự là kết thúc của một đường ống. Quá trình thay thế chồng chéo với chuyển hướng . Tuy nhiên, điều này có lẽ là một chút quá hạn chế về mặt kỹ thuật, điều này đưa chúng ta đến phần chú thích ...


  1. foo bartrong trường hợp này có thể là một hàm shell bên trong, trong trường hợp đó nó không có IO xử lý. Sự tồn tại của lớp vỏ tích hợp ít rõ ràng che khuất sự khác biệt này. Về nội dung, đầu vào và đầu ra sẽ giống nhau.

Tôi thích cách giải thích này, nhưng làm thế nào một hình vuông có thể mở rộng tên tệp , điều này chắc chắn tạo ra một tập hợp tên tệp như là kết quả của một hoạt động (một thuật toán phù hợp).
De Novo

Chắc chắn, nhưng để chơi ngữ nghĩa, không phải là "trích xuất giá trị của một định danh" (cái mà tôi gọi là một bản mở rộng) cũng là một hoạt động, do đó là một sự thay thế? Đặc biệt là vì "có những sự thay thế được coi là một phần của việc mở rộng tổng thể". Tức là, mối quan hệ giữa những từ này không giống với sự phân biệt giữa trái và phải. Tôi nghĩ rằng việc mở rộng tên tệp phù hợp với định nghĩa ban đầu của tôi về việc mở rộng, nhưng tôi đã làm rõ những điều về sự thay thế ở trên để giúp làm rõ hơn tại sao nó không như vậy.
goldilocks

Rắc rối mà tôi đã giải thích bằng cách giải thích trực quan khác với việc mở rộng tên tệp không phải là tôi muốn các thuật ngữ được xác định riêng, nhưng việc mở rộng tên tệp đó dường như không lấy ra một giá trị ràng buộc với một định danh. Trong một lớp vỏ nhất định, giá trị của một quả cầu nhất định sẽ phụ thuộc vào nhiều thứ chứ không chỉ toàn cầu và cùng một quả cầu có thể tạo ra các đầu ra khác nhau trong các bối cảnh khác nhau. Hơn nữa, không cần phải ràng buộc giá trị để lấy nó sau này. Mối quan hệ không phải là tùy ý (như trong foo = "bất cứ điều gì bạn thích"; echo "$ foo"), mà là tính toán và kết quả.
De Novo

Tôi cho rằng mối quan hệ giữa biểu thức và giá trị trong mở rộng số học cũng không (chính xác) tùy ý, nhưng chắc chắn chỉ có một giá trị cho một mở rộng nhất định, bất kể bối cảnh. Tôi chỉ có thể là nitpicking ở đây, nhưng trong tất cả các mở rộng vỏ, mở rộng tên tệp dường như là người đàn ông kỳ lạ, đưa ra lời giải thích này.
De Novo

2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Tôi nghĩ rằng sự khác biệt nói chung là quá tối thiểu để đáng được chú ý - và các thuật ngữ thường được sử dụng thay thế cho nhau. Mặc dù vậy, nếu bạn nhìn vào trên hai trường hợp, bạn có thể thấy rằng trong ví dụ đầu tiên chúng ta thay thế $1 cho $2là kết quả của sự mở rộng của $2. Ngay khi $2không thể được mở rộng , không có sự thay thế.

goldilocks làm cho một điểm tốt về sự tồn tại thanh tao của sự thay thế. Kiểu như con mèo của Schrodinger, tôi đoán vậy. Nó làm tôi nhớ một cái gì đó. Bạn có thể không quen thuộc với hình thức mở rộng tham số do POSIX chỉ định này, nhưng nó hoạt động theo cách ngược lại với hình thức trên:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Bây giờ đôi khi tôi muốn hành vi tương tự nhưng cho một setgiá trị. POSIX không chỉ định hành vi đó cho bất cứ điều gì chính xác. Nhưng, với một hoặc hai mẹo, nó chỉ đơn giản được quản lý:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Nhưng:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
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.