Xuất khẩu ở đâu var = value không có sẵn?


31

Tôi đã chọn - có lẽ trên Usenet vào giữa những năm 1990 (!) - đó là công trình

export var=value

là một Bashism, và biểu thức di động là

var=value
export var

Tôi đã ủng hộ điều này trong nhiều năm, nhưng gần đây, ai đó đã thách thức tôi về điều đó và tôi thực sự không thể tìm thấy bất kỳ tài liệu nào để sao lưu những gì từng là niềm tin vững chắc của tôi.

Googling cho "export: command not found"dường như không đưa ra bất kỳ trường hợp nào mà ai đó thực sự có vấn đề này, vì vậy ngay cả khi nó là chính hãng, tôi đoán nó không phổ biến lắm.

(The hits tôi nhận được dường như là người mới, người sao chép / dán dấu chấm câu, và kết thúc với 'export: command not foundhoặc một số như vậy, hoặc cố gắng sử dụng exportvới sudo; và người mới csh. Người dùng cố gắng sử dụng cú pháp Bourne shell)

Tôi chắc chắn có thể nói rằng nó hoạt động trên OS X, và trên nhiều distro Linux, bao gồm những nơi shdash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

Trong thế giới ngày nay, có an toàn để nói rằng export var=valuean toàn để sử dụng?

Tôi muốn hiểu hậu quả là gì. Nếu nó không thể chuyển sang v7 "Bourne classic", điều đó khó hơn nhiều so với những chuyện vặt vãnh. Nếu có các hệ thống sản xuất mà shell thực sự không thể đối phó với cú pháp này, điều đó sẽ hữu ích để biết.


2
cảm ơn cuối cùng tôi đã hiểu lý do tại sao tôi thường thấy điều mà tôi nghĩ là vô dụng: var = value; export var
Thorsten Staerk 28/03/2015

2
Vẫn còn một vài hộp Solaris đang hoạt động, và chúng nổi tiếng là thanh đạm trong các công cụ tiêu chuẩn của chúng; ở phía bên kia của quang phổ, không busyboxđi kèm với vỏ tối thiểu của riêng mình? (Tôi không ở vị trí để thử ngay thứ hai này.)
Ulrich Schwarz

Cảm ơn Ulrich, Solaris có thể là thủ phạm tại sao cú pháp dài này vẫn còn tồn tại.
Thorsten Staerk 28/03/2015

Câu trả lời:


20
export foo=bar

đã không được hỗ trợ bởi vỏ Bourne (một vỏ cũ từ những năm 70 mà từ đó các shtriển khai hiện đại như dẫn xuất tro / bash / ksh / yash / zsh). Điều đó đã được giới thiệu bởi ksh.

Trong vỏ Bourne, bạn sẽ làm:

foo=bar export foo

hoặc là:

foo=bar; export foo

hoặc với set -k:

export foo foo=bar

Bây giờ, hành vi của:

export foo=bar

thay đổi từ vỏ này sang vỏ khác.

Vấn đề là các bài tập và các đối số lệnh đơn giản được phân tích cú pháp và diễn giải khác nhau.

foo=bartrên được giải thích bởi một số shell như là một đối số lệnh và bởi những người khác như là một nhiệm vụ (đôi khi).

Ví dụ,

a='b c'
export d=$a

được hiểu là:

'export' 'd=b' 'c'

với một số shell ( ash, phiên bản cũ hơn của zsh(trong mô phỏng sh), yashvà:

'export' 'd=b c'

trong những người khác ( bash, ksh).

Trong khi

export \d=$a

hoặc là

var=d
export $var=$a

sẽ được giải thích giống nhau trong tất cả các shell (như 'export' 'd=b' 'c') bởi vì dấu gạch chéo ngược hoặc ký hiệu đô la ngăn chặn các shell đó hỗ trợ nó để coi các đối số đó là các bài tập.

Nếu exportchính nó được trích dẫn hoặc kết quả của một số mở rộng (thậm chí một phần), tùy thuộc vào vỏ, nó cũng sẽ ngừng nhận được điều trị đặc biệt.

Xem " Các trích dẫn có cần thiết cho việc gán biến cục bộ không? " Để biết thêm chi tiết về điều đó.

Cú pháp Bourne mặc dù:

d=$a; export d

được giải thích giống nhau bởi tất cả các shell mà không có sự mơ hồ ( d=$a export dcũng sẽ hoạt động trong shell Bourne và shell tuân thủ POSIX nhưng không phải trong các phiên bản gần đây zshtrừ khi trong shthi đua).

Nó có thể trở nên tồi tệ hơn thế nhiều. Xem ví dụ rằng cuộc thảo luận gần đây vềbash khi nào mảng có liên quan.

(IMO, đó là một sai lầm khi giới thiệu tính năng đó ).


Tôi đã ngạc nhiên rằng dấu chấm phẩy không bắt buộc foo=bar export foo, vì tôi luôn thấy nó ở đó. Tôi biết xuất khẩu là một nội trang, nhưng tại sao foo=bar; foo=baz export foo; echo $foohành xử khác hơn foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 hỗ trợ Monica

3
@ jrw32982, vì đó là nội dung. Bạn vẫn nhận được rằng trong vỏ POSIX hiện đại nhưng chỉ dành cho đặc biệt builtins đó exportlà.
Stéphane Chazelas

Mặc dù nó thảo luận declare, nhưng không export, tôi khuyên mọi người quan tâm đến bảo mật nên đọc cuộc thảo luận tại liên kết mà StéphaneChazelas cung cấp cho bash.bugs .
John1024

Câu trả lời chính xác! Nhưng phải mất một thời gian dài để mọi thứ d=$a export dđược diễn giải giống nhau bởi tất cả các vỏ mà không có sự mơ hồ ;-)
Conny

@conny, d=$a export dkhông hoạt động nữa zsh, vì vậy tôi đã cập nhật câu trả lời. Xem chỉnh sửa.
Stéphane Chazelas

28

Nó không phải là một bashism mà là một cú pháp tuân thủ POSIX. Nó thực sự bắt đầu như một kshism cách đây khá lâu và sau đó được chấp nhận bởi hầu hết các shell dựa trên cú pháp Bourne. Ngoại lệ khét tiếng duy nhất là /bin/shtrên Solaris 10 trở lên, bám sát cú pháp shell Bourne cũ. Hy vọng, Solaris 11 sử dụng lớp vỏ tuân thủ POSIX như /bin/sh.

Nhân tiện, exportđã là một lệnh dựng sẵn trong vỏ Bourne di sản, do đó, việc tìm kiếm export: command not foundlà sai lệch.

Dưới đây là hành vi vỏ Bourne di sản khi exportđược kết hợp với ảnh hưởng:

$ export var=22
var=22: is not an identifier

Đối với những người hoài cổ, mã nguồn của trình bao Bourne gốc này có sẵn và có thể được biên dịch cho hầu hết các bản phân phối Unix và Linux.


Rất cám ơn về cái nhìn sâu sắc lịch sử và thông báo lỗi chính xác cho google cho! Rõ ràng khi nhìn lại, đỏ mặt ...
tripleee 28/03/2015

4
Đó không phải là mã nguồn của shell Bourne ban đầu, đó là một OpenSolaris sh đã được sửa đổi. Nó là vỏ Bourne nhưng sau khi trải qua nhiều thập kỷ tiến hóa. Vỏ Bourne ban đầu, được vận chuyển với Unix V7 có thể được tìm thấy tại Hội di sản Unix
Stéphane Chazelas

1
@ StéphaneChazelas Nói đúng ra, bạn vẫn như thường lệ. Tuy nhiên, xin lưu ý rằng tôi đã không viết "shell Bourne gốc" mà là "shell Bourne gốc" này khi tôi đề cập đến shell được sử dụng bởi Solaris 10 và mã nguồn của nó có thể được biên dịch trên các nền tảng hiện đại. Cũng lưu ý rằng trình bao Bourne có một số tính năng được thêm vào giữa năm 1977 và 1989 nhưng sau đó về cơ bản đã ngừng phát triển (chuyển bên ngoài / thích ứng với các nền tảng mới hơn và sửa lỗi) trong 25 năm qua.
jlliagre
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.