Là shell di động để chạy một lệnh trên cùng một dòng sau khi gán biến?


7

Có tiêu chuẩn nào bao gồm tính di động của việc chạy lệnh sau khi gán biến trên cùng một dòng không?

APPLE="cider" echo hi

Làm thế nào di động là một cái gì đó như thế? Nó sẽ hoạt động ở đâu và nó sẽ ở đâu?

Ngoài ra: tập lệnh shell của tôi bắt đầu bằng #! / Bin / sh nếu điều đó tạo ra sự khác biệt.

Câu trả lời:


6

Miễn là bạn đang sử dụng trình bao tuân thủ POSIX, có.

Từ định nghĩa POSIX của ngôn ngữ lệnh shell : (các điểm có liên quan được in đậm)

"Lệnh đơn giản" là một chuỗi các phép gán và chuyển hướng tùy chọn , trong bất kỳ chuỗi nào, tùy ý theo sau bởi các từ và chuyển hướng, được chấm dứt bởi một toán tử điều khiển.

Khi một lệnh đơn giản nhất định được yêu cầu phải được thực thi (nghĩa là khi bất kỳ cấu trúc có điều kiện nào như danh sách AND-OR hoặc câu lệnh tình huống không bỏ qua lệnh đơn giản), tất cả các mở rộng, gán và chuyển hướng sau đây sẽ được thực hiện phần đầu của văn bản lệnh đến cuối:

  1. Các từ được công nhận là bài tập biến đổi hoặc chuyển hướng theo Quy tắc ngữ pháp Shell được lưu để xử lý trong bước 3 và 4.

  2. Các từ không phải là bài tập biến đổi hoặc chuyển hướng sẽ được mở rộng. Nếu bất kỳ trường nào vẫn tiếp tục mở rộng, trường đầu tiên sẽ được coi là tên lệnh và các trường còn lại là đối số cho lệnh.

  3. Chuyển hướng phải được thực hiện như mô tả trong Chuyển hướng .

  4. Mỗi phép gán biến sẽ được mở rộng để mở rộng dấu ngã, mở rộng tham số, thay thế lệnh, mở rộng số học và xóa trích dẫn trước khi gán giá trị.

Trong danh sách trước, thứ tự của bước 3 và 4 có thể được đảo ngược để xử lý các tiện ích tích hợp đặc biệt; xem các tiện ích tích hợp đặc biệt .

Nếu không có kết quả tên lệnh, việc gán biến sẽ ảnh hưởng đến môi trường thực thi hiện tại. Mặt khác, các phép gán biến sẽ được xuất cho môi trường thực thi của lệnh và sẽ không ảnh hưởng đến môi trường thực thi hiện tại (ngoại trừ các tích hợp đặc biệt).


Ngoài ra, có #!/bin/shvấn đề. Từ định nghĩa POSIX củash :

Tiện ích sh là một trình thông dịch ngôn ngữ lệnh sẽ thực thi các lệnh được đọc từ một chuỗi dòng lệnh, đầu vào tiêu chuẩn hoặc một tệp được chỉ định. Ứng dụng phải đảm bảo rằng các lệnh được thực thi được thể hiện bằng ngôn ngữ được mô tả trong Ngôn ngữ lệnh Shell .

Vì vậy, về cơ bản nó nói rằng shphải tuân theo các quy tắc chúng tôi đề cập ở trên.

Vì vậy, miễn là bạn đang sử dụng HĐH tuân thủ POSIX, bạn vẫn ổn.


Một nhận xét nhỏ về điểm cuối cùng của bạn. Mặc dù POSIX bắt buộc shphải tuân thủ tiêu chuẩn, nhưng nó không chỉ định đường dẫn nào shphải có nên /bin/shkhông nhất thiết phải là vỏ POSIX và thực sự là vỏ Bourne kế thừa trên một số nền tảng (hiện tại là Solaris 10 trở lên). Điều này sẽ không bị tổn thương trong trường hợp gán biến cụ thể này vì cú pháp này dài trước tiêu chuẩn POSIX.
jlliagre

Nó không bắt buộc rằng nó cư trú tại /bin/shkhông. Nhưng nó bắt buộc shphải cư xử thế nào . Đó là tất cả những gì quan trọng. Bạn không thể dính thứ gì khác được gọi vào shđó và tuân thủ POSIX.
Patrick

Điều này là không chính xác. Hệ điều hành tuân thủ POSIX được cung cấp miễn phí không tuân thủ POSIX /bin/sh. Điều bắt buộc là khi sử dụng đường dẫn tuân thủ, nghĩa là PATH=$(getconf PATH), việc chạy shsẽ gọi trình bao tuân thủ POSIX.
jlliagre

Cảm ơn Patrick. Để chạm vào những gì @jlliagre đã nói, tôi đã đọc rằng / bin / sh có thể là một vỏ tương thích bourne nhưng không nhất thiết phải tương thích POSIX? Điều đó có đúng không? Tôi đã cài đặt vỏ gia truyền (một cổng của vỏ bourne ban đầu) và nó đã thử nghiệm tốt với ví dụ của tôi. Tôi cũng đã thử nghiệm zsh trên Ubuntu chỉ để xem điều gì sẽ xảy ra và tôi không gặp phải bất kỳ lỗi nào như trong ví dụ của llua.
kiểm tra

1
@test Như tôi đã viết trong bình luận trước đây, var=x commandcú pháp có trước POSIX nên không có vấn đề gì khi sử dụng shell không dựa trên POSIX vẫn là Bourne trong trường hợp của bạn.
jlliagre

3

Để trả lời câu hỏi thứ hai, không đầy đủ (số lượng vỏ được mindboggling )

% for sh in dash ksh93 mksh rc fish bash zsh csh tcsh jsh; do
printf '%s\n' "$sh: $($sh -c 'var=foo echo hi')"
done

dash: hi
ksh93: hi
mksh: hi
rc: hi
fish: Unknown command var=foo”. Did you mean set var foo”? For information on assigning values to variables, see the help section on the set command by typing help set
Standard input: var=foo echo hi
                ^
fish:
bash: hi
zsh: hi
var=foo: Command not found.
csh:
var=foo: Command not found.
tcsh:
jsh: hi

Trong hầu hết các vỏ giống như Korn hiện đại, nó sẽ hoạt động. Nhưng tôi không nghĩ đó là một tiêu chuẩn, tôi chắc chắn một người như Stephane Chazelas sẽ biết mức độ phổ biến của nó.


Cú pháp này được sử dụng kể từ những ngày đầu của Bourne Shell vào năm 1976. Lưu ý rằng đó cshlà không chuẩn và zshtheo mặc định là không chuẩn.
hỏi


2

Đưa ra lệnh trong ví dụ của bạn, echosẽ chạy, nhưng những gì xảy ra $APPLEthì phức tạp hơn một chút.

Điều này đúng, như được chỉ ra trong câu trả lời của @ Patrick ở đây, rằng nếu shell gọi một quy trình thì tất cả các biến được khai báo trên dòng lệnh trước lệnh gọi của nó được chỉ định sẽ được xuất vào môi trường của nó. Và hơn nữa, các biến đó cũng được chỉ định hết hạn với quy trình được gọi - vì vậy ...

unset var; var=val cmd; echo ${var-unset.}

... nên in unset.

Nhưng nơi toàn bộ khái niệm này được một chút phức tạp hơn mặc dù, và như ví dụ của riêng bạn cho thấy, là tại thời điểm đó cmdkhông một quá trình Viện dẫn nhưng thay vào đó hoặc là một vỏ dựng sẵn, một chức năng vỏ, hoặc một đặc biệt vỏ được xây dựng trong tiện ích. Trong mỗi một trong ba trường hợp đó, shell rất có thể sẽ chỉ chạy một số thói quen của riêng nó trong bộ nhớ, và không gọi được gì cả.

Ví dụ, echogần như chắc chắn một lớp vỏ được xây dựng trong tiện ích - như hầu hết các vỏ tôi biết cung cấp cho nó như vậy - nhưng nó là không một POSIX chỉ định đặc biệt được xây dựng trong. Theo cách này, về cơ bản, nó là một hàm shell phải mô phỏng một thực thi bên ngoài. Điều này có lẽ được nêu rõ hơn một chút ở đây:

Thuật ngữ "tích hợp" ngụ ý rằng trình bao có thể thực thi trực tiếp tiện ích và không cần tìm kiếm nó. Việc triển khai có thể chọn làm cho bất kỳ tiện ích nào được tích hợp sẵn; tuy nhiên, các tiện ích tích hợp đặc biệt được mô tả ở đây khác với các tiện ích tích hợp thông thường ...

Các bài tập biến được chỉ định với các tiện ích tích hợp đặc biệt vẫn có hiệu lực sau khi hoàn thành tích hợp; điều này sẽ không xảy ra với một tiện ích tích hợp thông thường hoặc tiện ích khác.

Các tiện ích tích hợp đặc biệt trong phần này không cần phải được cung cấp theo cách có thể truy cập thông qua họ hàm thực thi được xác định trong khối Giao diện hệ thống của POSIX.1-2008.

Vì vậy, một biến được khai báo trên echodòng lệnh bị diệt echo, nhưng một biến được khai báo trên setdòng lệnh vẫn tồn tại - (mặc dù bashtheo mặc định vi phạm quy tắc này) . Điều tương tự cũng đúng khi cmdhàm shell :

Khi một hàm được thực thi, nó sẽ có các thuộc tính lỗi cú pháp và gán biến được mô tả cho các tiện ích tích hợp đặc biệt trong danh sách liệt kê ở đầu Tiện ích tích hợp đặc biệt.

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.