2010-05-29 29 views
80
false; echo $? 

Ở trên sẽ xuất ra 1, điều này mâu thuẫn với tất cả các ngôn ngữ lập trình khác mà tôi biết.Tại sao 0 là đúng nhưng sai là 1 trong vỏ?

Bất kỳ lý do nào trong điều này?

+3

Nó cũng phù hợp với cách Unix ... không trả lại bất cứ điều gì về thành công. –

+13

Vì trạng thái thoát không phải là boolean. Đơn giản như thế. – Jens

+0

Hãy nhớ rằng 'false' không phải là một boolean, như trong các ngôn ngữ lập trình khác. Nó chỉ là một chương trình nằm ở '/ bin/false' ('/usr/bin/false' trên máy Mac) có nghĩa là luôn luôn trả lại mã thoát lỗi 1. Tương tự cho 'true'. Vì vậy, không có gì như đúc ở đây. Nó chỉ là tất cả về các mã thoát. – Mike

Trả lời

14

Đó chỉ là quy ước rằng mã thoát 0 có nghĩa là thành công. EXIT_SUCCESS sẽ là 0 trên hầu hết mọi hệ thống hiện đại.

EDIT:

"? Tại sao cả hai thử nghiệm 0 và thử nghiệm 1 trả về 0 (thành công)"

Đó là một câu hỏi hoàn toàn khác. Câu trả lời là đi qua một đối số duy nhất để kiểm tra luôn luôn dẫn đến thành công trừ khi đối số đó là chuỗi rỗng (""). Xem Open Group documentation.

+0

Vậy tại sao cả 'test 0' và' test 1' trả về 0 (thành công)? – httpinterpret

+4

@httpinterpret, 'test' không kiểm tra giá trị số. Nó kiểm tra xem chuỗi đó có phải là chuỗi rỗng hay không. 'man test' để biết thêm thông tin. –

11

Thông thường chương trình trả về 0 để thành công, khác không cho thất bại; false trả về 1 vì nó là giá trị khác 0, nhưng thường có giá trị khác 0 có nghĩa là thất bại của một số loại, và nhiều chương trình sẽ trả về các giá trị khác 0 để chỉ ra các chế độ lỗi khác nhau

+1

Downvotes không có lời giải thích (hoặc lý do rõ ràng) bất cứ điều gì hút và những người làm điều đó là lame bởi vì họ không giúp đỡ cộng đồng ở tất cả. –

+1

Không bỏ qua nó… nhưng nó * là * 2 điểm của họ… và @MichaelMrozek .. với 19.6k, nó không thể làm tổn thương quá tệ, lol. –

+1

@alexgray Đây là hai năm trước; tại thời điểm tôi có khoảng 5k. Và tôi đã tò mò hơn những gì đã sai với câu trả lời hơn về các đại diện –

63

Đó là quy ước, nhưng đặc biệt hữu ích khi bạn nghĩ về nó. Nói chung, nếu một chương trình thành công, đó là tất cả những gì bạn cần biết. Tuy nhiên, nếu thất bại, bạn có thể cần phải biết tất cả các loại thông tin về lỗi - tại sao nó xảy ra, cách khắc phục, vv. Không có nghĩa là 'thành công' và thất bại có nghĩa là không cho phép bạn kiểm tra khá dễ dàng để thành công và điều tra lỗi cụ thể để biết thêm chi tiết nếu bạn muốn. Rất nhiều API và khung công tác có một quy ước tương tự - hàm trả về thành công 0 và các hàm không trả lại mã lỗi mô tả trường hợp lỗi cụ thể.

+3

Tôi hiểu câu trả lời này, nhưng tôi vẫn không nhận được lý do tại sao bool để chuyển đổi int là đảo ngược. Có một "boolean return" trả về: nếu bạn trả về true, nó có nghĩa là không có lỗi, nếu bạn trả về false, nó có nghĩa là đã xảy ra lỗi (như "integer = error code convention"). – Guillaume86

44

Bash là ngôn ngữ lập trình (kịch bản), nhưng nó cũng là một trình bao và giao diện người dùng. Nếu 0 là lỗi, thì chương trình chỉ có thể trình bày một loại lỗi.

Tuy nhiên trong Bash, mọi giá trị khác không phải là lỗi và chúng tôi có thể sử dụng bất kỳ số nào từ 1-255 để biểu thị lỗi. Điều này có nghĩa là chúng tôi có thể có nhiều loại lỗi khác nhau. 1 là lỗi chung, 126 có nghĩa là không thể thực thi tệp, 127 có nghĩa là 'không tìm thấy lệnh', v.v. Dưới đây là danh sách Bash Reserved Exit Codes hiển thị một số mã thoát phổ biến nhất.

Ngoài ra còn có nhiều loại thành công (trạng thái thoát là 0). Tuy nhiên, thành công sẽ cho phép bạn tiến hành bước tiếp theo — bạn có thể thích kết quả in ra màn hình hoặc thực hiện lệnh, v.v.

+3

Câu trả lời thực tế này cho thấy tính hữu ích của nhiều mã trả lại thích hợp hơn với tính thuyết giảng của một số câu trả lời khác. – javadba

+0

Và chỉ để giải trí, tôi sẽ chỉ ra rằng ['/ usr/include/sysexits.h' ghi chú các giá trị thoát] (https://www.freebsd.org/cgi/man.cgi?query=sysexits) có lẽ có nhiều nguyện vọng hơn, mặc dù quy ước họ đại diện cho những năm 1980. Quy ước này tồn tại bên ngoài phạm vi của bash. – ghoti

14

Điểm cơ bản mà tôi thấy quan trọng cần hiểu là điều này. Trong bash và trong unix shells nói chung, các giá trị trả về không phải là boolean. Chúng là các mã số nguyên. Như vậy, bạn phải đánh giá chúng theo quy ước nói 0 có nghĩa là thành công, và các giá trị khác có nghĩa là một số lỗi.

Với các nhà điều hành test, [ ] hoặc [[ ]], điều kiện bash được đánh giá là đúng trong trường hợp mã thoát 0 (kết quả của/bin/true).Nếu không, họ đánh giá là sai.

Strings được đánh giá khác biệt so với mã lối ra:

if [ 0 ] ; then echo not null ; fi 
if [ $(echo 0) ] ; then echo not null ; fi 

if [ -z "" ] ; then echo null ; fi 

Các toán tử số học (()) dịch 1 và 0 là đúng và sai. Nhưng toán tử đó không thể được sử dụng như một sự thay thế hoàn toàn cho test, [ ] hoặc [[ ]]. Dưới đây là một ví dụ cho thấy khi các toán tử số học rất hữu ích:

for ((counter = 0 ; counter < 10 ; counter ++)) ; do 
    if ((counter % 2)) ; then echo "odd number $counter" ; fi 
done 
+0

Cảm ơn bạn đã giải thích về dấu ngoặc và dấu ngoặc đơn trên đúng/false – javadba

16

Có hai vấn đề liên quan ở đây.

Đầu tiên, câu hỏi của OP, Tại sao 0 là đúng nhưng sai là 1 trong vỏ? và thứ hai, tại sao các ứng dụng trả về 0 để thành công và khác không cho thất bại?

Để trả lời câu hỏi của OP, chúng tôi cần hiểu câu hỏi thứ hai. Rất nhiều câu trả lời cho bài đăng này đã mô tả rằng đây là một quy ước và đã liệt kê một số điều kỳ diệu mà quy ước này quy định. Một số trong những niceties được tóm tắt dưới đây.

Tại sao các ứng dụng trả về 0 để thành công và khác không cho thất bại?

Mã yêu cầu hoạt động cần biết hai điều về trạng thái thoát của thao tác. Lối thoát hoạt động có thành công không? [* 1] Và nếu thao tác không thoát thành công tại sao lối thoát hoạt động không thành công? Bất kỳ giá trị nào cũng có thể được sử dụng để biểu thị thành công. Nhưng 0 thuận tiện hơn bất kỳ số nào khác vì nó di động giữa các nền tảng. Tóm tắt câu trả lời của xibo cho số này question vào ngày 16 tháng 8 năm 2011:

Không độc lập về mã hóa.

Nếu chúng tôi muốn lưu trữ một (1) trong một số nguyên 32 bit, câu hỏi đầu tiên sẽ là "từ lớn hoặc từ nhỏ?", Theo sau là "byte dài bao nhiêu một chút từ -endian? ", trong khi số không sẽ luôn giống nhau.

Ngoài ra, nó cũng cần được mong đợi rằng một số người đã tạo ra lỗi không liên quan hoặc ngắn tại một số điểm hoặc thậm chí là nổi. (int) ((char) ENOLCK) không phải là ENOLCK khi char không dài ít nhất 8 bit (các máy char ASCII 7 bit được UNIX hỗ trợ), trong khi (int) ((char) 0) là 0 độc lập với chi tiết kiến ​​trúc của char.

Khi xác định 0 sẽ là giá trị trả về thành công, thì có nghĩa là sử dụng bất kỳ giá trị khác không cho thất bại. Điều này cho phép nhiều số exit codes trả lời câu hỏi tại sao thao tác thất bại.

Tại sao 0 là đúng nhưng sai là 1 trong vỏ?

Một trong những cách sử dụng cơ bản của trình bao là tự động hóa quy trình bằng cách viết kịch bản cho chúng. Thông thường, điều này có nghĩa là gọi một phép toán và sau đó thực hiện một điều gì khác có điều kiện dựa trên trạng thái thoát của hoạt động.Philippe A. giải thích rõ ràng trong câu trả lời của mình cho bài đăng này là

Trong bash và trong vỏ unix nói chung, giá trị trả về không phải là boolean. Chúng là các mã số nguyên.

Cần thiết để diễn giải trạng thái thoát của các hoạt động này dưới dạng giá trị boolean. Nó có ý nghĩa để ánh xạ trạng thái thoát thành công (0) thành true và bất kỳ trạng thái thoát khác không thành công/lỗi thành sai. Làm điều này cho phép thực thi có điều kiện các lệnh shell bị chặn.

Dưới đây là ví dụ mkdir deleteme && cd $_ && pwd. Bởi vì shell diễn giải 0 là true nên lệnh này thuận tiện như mong đợi. Nếu shell giải thích 0 là false thì bạn phải đảo ngược trạng thái thoát đã diễn giải cho mỗi thao tác.

Tóm lại, sẽ là vô nghĩa đối với trình dịch diễn giải 0 là sai theo quy ước rằng các ứng dụng trả về 0 cho trạng thái thoát thành công.


[* 1]: Có, nhiều lần hoạt động cần trả lại nhiều hơn một thông điệp thành công đơn giản nhưng nằm ngoài phạm vi của chuỗi này.

cũng Appendix E Xem trong Advanced Bash-Scripting Guide

+1

Xin chào, Chỉ cần nhấn mạnh rằng, nếu trình bao được hiểu là số không sai và không phải là true, mẹo thực hiện 'mkdir deleteme && cd _ $ && pwd' sẽ không thực sự thất bại; nhưng chúng ta sẽ phải thay thế nó bằng 'mkdir deleteme || cd _ $ || pwd', mà theo tôi ít rõ ràng hơn, bởi vì những gì chúng ta thực sự muốn làm là 'mkdir deleteme'“ _and_ ”' cd _ $ '“ _and_ ”' pwd' ... (với “và” ở đây nghĩa của nó từ ngôn ngữ thông thường). –

+1

Tôi nghĩ rằng tôi đã đề cập đến điều đó trong câu trả lời của mình. Rõ ràng, khi bạn đảo ngược logic, không đủ để thay thế toán tử '&&' bằng toán tử '||'. Bạn sẽ cần phải áp dụng đầy đủ luật của De Morgan. Xem: http://en.wikipedia.org/wiki/De_Morgan%27s_laws – axiopisty

+0

Xem xét khác: Tôi thấy ít nhất ba lý do tại sao, trên cơ sở chung, sẽ là tự nhiên khi nói rằng 'true' tương ứng với số không và' false 'tương ứng với nonzero. Đầu tiên, nếu tôi nói với bạn điều gì đó, "đã nói với bạn sự thật" phụ thuộc vào số lời nói dối mà tôi đã nói: hoặc là bằng không và tôi đã nói (trên toàn cầu) sự thật, hoặc nó không phải là nonzero và tôi đã nói dối. Về cơ bản, điều này giống với việc muốn hợp lý 'và' tương ứng với" và "bổ sung chung (khi hạn chế đến số tự nhiên, rõ ràng). –

3

bạn cố gắng để đánh đồng đúng/sai với thành công/thất bại.

Họ là hai hoàn toàn, mặc dù tinh tế lúc đầu, các dichotomies khác nhau!

Trong kịch bản lệnh shell, không có điều gì là đúng/sai. Shell 'biểu thức' không được hiểu là đúng/sai. Thay vào đó, biểu thức shell là các quá trình thành công hoặc thất bại.

Rõ ràng, quá trình có thể không thành công vì nhiều lý do. Vì vậy, chúng ta cần một bộ mã lớn hơn để ánh xạ các lỗi có thể xảy ra. Các số nguyên dương làm các trick. Mặt khác, nếu quá trình thành công, điều đó có nghĩa là nó đã làm chính xác những gì nó được cho là phải làm. Vì chỉ có một cách để làm điều đó, chúng tôi chỉ cần một mã. 0 không lừa.

Trong C, chúng tôi đang tạo một chương trình. Trong một kịch bản lệnh shell, chúng tôi đang chạy một loạt các chương trình để hoàn thành công việc.

Sự khác biệt!

+0

Thật khó hiểu. Nhập 'man ['. Nó cho thấy Tiện ích kiểm tra đánh giá biểu thức và, nếu nó đánh giá đúng, trả về một trạng thái thoát (không) đúng (không); nếu không , nó trả về 1 (sai). Nếu không có biểu thức, phép thử cũng trả về 1 (sai). – cavalcade

+0

Ngoài ra [man [] (http://i.imgur.com/5Cuoec6.png) – cavalcade

2

đó là một quy ước có niên đại từ những ngày đầu của Unix.

Theo quy ước, tất cả các cuộc gọi hệ thống trả về 0 nếu thành công, khác 0, vì các số khác nhau có thể được sử dụng để cho biết lý do thất bại khác nhau.

Vỏ theo quy ước này, 0 có nghĩa là lệnh cuối cùng đã thành công, khác không. Tương tự, giá trị trả về khác không có ích cho các thông báo lỗi đầu ra: ví dụ: 1: "não chết", 2: "nhẫn tâm", v.v.

Các vấn đề liên quan