Sự khác biệt giữa câu lệnh return
và exit
câu lệnh trong hàm Bash đối với mã thoát là gì?
Sự khác biệt giữa câu lệnh return
và exit
câu lệnh trong hàm Bash đối với mã thoát là gì?
Câu trả lời:
Từ man bash
trên return [n]
;
Làm cho một hàm dừng thực thi và trả về giá trị được chỉ định bởi n cho người gọi nó. Nếu n bị bỏ qua, trạng thái trả về là trạng thái của lệnh cuối cùng được thực thi trong thân hàm.
... trên exit [n]
:
Làm cho vỏ thoát ra với trạng thái n. Nếu n bị bỏ qua, trạng thái thoát là trạng thái của lệnh cuối cùng được thực thi. Một cái bẫy trên EXIT được thực thi trước khi shell kết thúc.
BIÊN TẬP:
Theo chỉnh sửa câu hỏi của bạn, liên quan đến mã thoát, return
không liên quan gì đến mã thoát. Mã thoát được dành cho các ứng dụng / tập lệnh , không phải chức năng. Vì vậy, về vấn đề này, từ khóa duy nhất đặt mã thoát của tập lệnh (từ khóa có thể bị bắt bởi chương trình gọi bằng $?
biến shell) là exit
.
EDIT 2:
Tuyên bố cuối cùng của tôi đề cập đến exit
là gây ra một số ý kiến. Nó được tạo ra để phân biệt return
và exit
theo cách hiểu của OP, và trên thực tế, tại bất kỳ điểm nào của tập lệnh chương trình / shell, exit
là cách duy nhất để kết thúc tập lệnh với mã thoát cho quy trình gọi.
Mỗi lệnh thực hiện trong vỏ tạo ra một "mã thoát" địa phương: nó đặt $?
biến để mã đó, và có thể được sử dụng với if
, &&
và các nhà khai thác khác để có điều kiện thực hiện các lệnh khác.
Các mã thoát này (và giá trị của $?
biến) được đặt lại theo từng lệnh thực thi.
Ngẫu nhiên, mã thoát của lệnh cuối cùng được thực thi bởi tập lệnh được sử dụng làm mã thoát của chính tập lệnh mà quá trình gọi.
Cuối cùng, các hàm, khi được gọi, hoạt động như các lệnh shell đối với các mã thoát. Mã thoát của hàm ( trong hàm) được đặt bằng cách sử dụng return
. Vì vậy, khi trong một chức năng return 0
được chạy, việc thực thi chức năng chấm dứt, đưa ra mã thoát là 0.
func(){ return 50; };func;echo $?
lặp lại 50. Vì vậy, $?
biến shell dường như không bị giới hạn exit
.
$?
Mở rộng đến trạng thái thoát của đường ống tiền cảnh được thực hiện gần đây nhất." Lối ra đó có thể từ shell dưới dạng một cuộc gọi đến exit
(hoặc nhấn vào cuối tập lệnh) hoặc ở dạng một cuộc gọi đến return
trong một chức năng.
$?
Quá trình / tập lệnh hiện tại bị giới hạn ở exit
hoặc kết quả của lệnh cuối cùng được thực thi bởi tập lệnh này. Vì vậy, nếu dòng script cuối cùng của bạn là lệnh gọi hàm đó và hàm đó trả về 50, vâng, cái $?
mà bạn tạo ra cho quá trình gọi bạn là 50. Tuy nhiên, điều đó không phải làm với return
, bởi vì đây là giới hạn trong kịch bản hiện tại. Nó chỉ xảy ra được trả về nếu lệnh gọi hàm này là câu cuối cùng của tập lệnh. exit
tuy nhiên, luôn hoàn thành tập lệnh và trả lại giá trị đó $?
cho quy trình gọi .
return
không liên quan gì đến mã thoát". Thử nghiệm cho tôi biết rằng không có sự khác biệt về chức năng giữa mã trả về của hàm và mã thoát của tập lệnh.
return
sẽ làm cho hàm hiện tại đi ra khỏi phạm vi, trong khi đó exit
sẽ khiến tập lệnh kết thúc tại điểm được gọi. Đây là một chương trình mẫu để giúp giải thích điều này:
#!/bin/bash
retfunc()
{
echo "this is retfunc()"
return 1
}
exitfunc()
{
echo "this is exitfunc()"
exit 1
}
retfunc
echo "We are still here"
exitfunc
echo "We will never see this"
$ ./test.sh
this is retfunc()
We are still here
this is exitfunc()
$?
.
echo fnord | while read x; do exitfunc; done; echo "still here"
sẽ in "vẫn ở đây". Có vẻ như chỉ có while
lớp vỏ phụ được thoát ra trong kịch bản này.
done || exit $?
nhưng điều đó là xấu xí và không chính xác tương đương.
return
sẽ khiến hàm hiện tại hoặc tập lệnh có nguồn gốc đi ra khỏi phạm vi```.
Tôi không nghĩ có ai thực sự trả lời đầy đủ câu hỏi vì họ không mô tả cách hai người được sử dụng. OK Tôi nghĩ rằng chúng ta biết rằng lối thoát sẽ giết chết tập lệnh, bất cứ khi nào nó được gọi và bạn có thể gán trạng thái cho nó cũng như thoát hoặc thoát 0 hoặc thoát 7, v.v. Điều này có thể được sử dụng để xác định cách tập lệnh bị buộc dừng lại nếu được gọi bởi tập lệnh khác, vv Đủ khi thoát.
return khi được gọi sẽ trả về giá trị được chỉ định để biểu thị hành vi của hàm, thường là 1 hoặc 0. Ví dụ:
#!/bin/bash
isdirectory() {
if [ -d "$1" ]
then
return 0
else
return 1
fi
echo "you will not see anything after the return like this text"
}
kiểm tra như thế này:
if isdirectory $1; then echo "is directory"; else echo "not a directory"; fi
hoặc như thế này:
isdirectory || echo "not a directory"
Trong ví dụ này, kiểm tra có thể được sử dụng để chỉ ra nếu thư mục được tìm thấy. lưu ý rằng bất cứ điều gì sau khi trả về sẽ không được thực thi trong hàm. 0 là đúng nhưng sai là 1 trong vỏ, khác với các lang prog khác.
Để biết thêm thông tin về các chức năng: http://www.linuxjournal.com/content/return-values-bash-fifts
LƯU Ý: Hàm isdirectory chỉ dành cho mục đích hướng dẫn. Đây không phải là cách bạn thực hiện một tùy chọn như vậy trong một kịch bản thực sự.
test -d $1
để đạt được kết quả tương tự. Không bao giờ làm if <check> return else return
. <check>
một mình sẽ làm điều tương tự trong tất cả các ngôn ngữ mà tôi biết ít nhất.
isdirectory() { [ -d "$1" ]; }
sẽ hành xử chính xác giống như những gì bạn có ở đây: Giá trị trả về mặc định của hàm shell, cho dù bằng cách đạt đến cuối mã của nó hoặc bởi return
không có đối số, là của lệnh gần đây nhất.
return
tuyên bố. Đúng là ví dụ của ông rất đơn giản và không được sử dụng trong sản xuất. Nhưng nó đơn giản, vì vậy nó hoàn thành tốt nhiệm vụ của mình. Không có gì sai với nó.
Hãy nhớ rằng, các hàm là nội bộ của một tập lệnh và thường trả về từ khi chúng được gọi bằng cách sử dụng câu lệnh return. Gọi một tập lệnh bên ngoài hoàn toàn là một vấn đề khác và các tập lệnh thường kết thúc bằng một câu lệnh thoát.
Sự khác biệt "giữa câu lệnh return và exit trong các hàm BASH liên quan đến mã thoát" là rất ít. Cả hai trả về một trạng thái, không phải giá trị mỗi se. Trạng thái bằng 0 biểu thị thành công, trong khi bất kỳ trạng thái nào khác (1 đến 255) biểu thị sự thất bại. Câu lệnh return sẽ quay trở lại tập lệnh từ nơi nó được gọi, trong khi câu lệnh thoát sẽ kết thúc toàn bộ tập lệnh từ bất kỳ nơi nào nó gặp phải.
return 0 # returns to where the function was called. $? contains 0 (success).
return 1 # returns to where the function was called. $? contains 1 (failure).
exit 0 # exits the script completely. $? contains 0 (success).
exit 1 # exits the script completely. $? contains 1 (failure).
Nếu chức năng của bạn đơn giản kết thúc mà không có câu lệnh return, trạng thái của lệnh cuối cùng được thực thi sẽ được trả về dưới dạng mã trạng thái (và sẽ được đặt vào $?
).
Hãy nhớ rằng, trả lại và thoát trả lại mã trạng thái từ 0 đến 255, có sẵn trong $?
. Bạn không thể nhét bất cứ thứ gì khác vào mã trạng thái (ví dụ: trả về "cat"); nó sẽ không làm việc. Nhưng, một tập lệnh có thể trả lại 255 lý do khác nhau cho sự thất bại bằng cách sử dụng mã trạng thái.
Bạn có thể đặt các biến có trong tập lệnh gọi hoặc kết quả echo trong hàm và sử dụng thay thế lệnh trong tập lệnh gọi; nhưng mục đích của việc trả lại và thoát là để truyền mã trạng thái, không phải giá trị hoặc kết quả tính toán như người ta có thể mong đợi trong một ngôn ngữ lập trình như C.
Đôi khi, bạn chạy một kịch bản bằng cách sử dụng .
hoặc source
.
. a.sh
Nếu bạn bao gồm một exit
trong a.sh
, nó sẽ không chỉ chấm dứt tập lệnh, mà kết thúc phiên shell của bạn.
Nếu bạn bao gồm một return
trong a.sh
, nó chỉ đơn giản dừng xử lý tập lệnh.
return: can only 'return' from a function or sourced script
, điều này làm cho nó không phù hợp với tập lệnh chung.
all
tình huống. Sử dụng .
hoặc source
chạy tập lệnh trong trình bao hiện tại, thay vì sinh ra một trình bao phụ. Kịch bản phải biết nó được sử dụng như thế nào. Khốn cho người dùng làm điều đó ngược lại. Cá nhân, tôi khuyên bạn nên đọc kịch bản trước khi chạy chúng lần đầu tiên.
trap
chức năng cho ERR EXIT
và sau đó đầu tiên tiết kiệm mã lối ra của một lệnh thất bại errCode=$?
và sau đó thoát khỏi kịch bản (có nguồn gốc hay không) với return $errCode || exit $errCode
nơi ||
có nghĩa là "nếu tôi không thể trở về vì tôi đã không có nguồn gốc , chỉ cần thoát ra thay thế ".
Nói một cách đơn giản (chủ yếu dành cho người mới viết mã), chúng ta có thể nói,
`return` : exits the function,
`exit()` : exits the program(called as process while running)
Ngoài ra Nếu bạn quan sát, điều này rất cơ bản nhưng ...,
`return` : is the keyword
`exit()` : is the function
exit
không có nhiều hơn hoặc ít hơn một chức năng hơn return
. Chúng là các lệnh tích hợp. Chúng thậm chí không phải là từ dành riêng.
exit
chấm dứt quá trình hiện tại ; có hoặc không có mã thoát, hãy coi đây là một hệ thống nhiều hơn một chức năng của chương trình. Lưu ý rằng khi tìm nguồn cung ứng, exit
sẽ kết thúc shell, tuy nhiên, khi chạy sẽ chỉ exit
là tập lệnh.
return
từ một chức năng quay trở lại hướng dẫn sau cuộc gọi, có hoặc không có mã trả về. return
là tùy chọn và nó ẩn ở cuối hàm. return
chỉ có thể được sử dụng bên trong một chức năng.
Tôi muốn thêm rằng trong khi có nguồn gốc, không dễ để exit
tập lệnh từ bên trong một hàm mà không làm chết trình bao. Tôi nghĩ rằng, một ví dụ tốt hơn trong kịch bản 'kiểm tra'
#!/bin/bash
function die(){
echo ${1:=Something terrible wrong happen}
#... clean your trash
exit 1
}
[ -f /whatever/ ] || die "whatever is not available"
# now we can proceed
echo "continue"
làm như sau:
user$ ./test
Whatever is not available
user$
test
-và vỏ sẽ đóng lại.
user$ . ./test
Whatever is not available
chỉ test
sẽ kết thúc và lời nhắc sẽ hiển thị.
Giải pháp là bao gồm các thủ tục có khả năng trong (
và)
#!/bin/bash
function die(){
echo $(1:=Something terrible wrong happen)
#... clean your trash
exit 1
}
( # added
[ -f /whatever/ ] || die "whatever is not available"
# now we can proceed
echo "continue"
) # added
Bây giờ, trong cả hai trường hợp test
sẽ chỉ thoát.
(
và )
đặt khối đó vào lớp vỏ phụ, thực hiện không thực hiện lệnh .
(nguồn) như thể bạn đã chạy tập lệnh kiểm tra bình thường, nằm trong lớp vỏ phụ. IOf script không được chạy với .
hoặc source
sau đó bạn thực sự có 2 shell con.
Câu hỏi của OP: Sự khác biệt giữa câu lệnh return và exit trong các hàm BASH đối với mã thoát là gì?
Firtly, một số làm rõ là cần thiết:
Trong danh sách dấu đầu dòng ở trên, chọn từ "(x | y)" luôn là mục đầu tiên hoặc luôn là mục thứ hai để nhận các câu lệnh về hàm & return hoặc shell & exit tương ứng.
Điều rõ ràng là cả hai đều chia sẻ cách sử dụng chung của biến đặc biệt $? để vượt qua các giá trị trở lên sau khi chúng chấm dứt.
* Bây giờ cho những cách đặc biệt mà $? có thể thiết lập:
Điều đáng chú ý là $? có thể được gán một giá trị bằng cách gọi exit trong shell phụ, như thế này:
# (exit 259)
# echo $?
3
exit 259
echos như 3
vì giá trị xuất cảnh cuối cùng là một byte duy nhất. 259 % 256 = 3
Trước hết, return
là một từ khóa và exit
bạn tôi là một chức năng.
Điều đó nói rằng, đây là một cách giải thích đơn giản nhất.
return
Nó trả về một giá trị từ một hàm.
exit
Nó thoát ra hoặc từ bỏ lớp vỏ hiện tại.
return
là một từ khóa. Trả về không chỉ là mã thoát, đó là lý do tại sao việc so sánh không công bằng.
exit
phải return
là "từ khóa", hoặc, như hướng dẫn bash gọi chúng là "từ dành riêng". Cả hai đều không phải là "hàm", theo nghĩa của hàm bash. Cả hai đều là lệnh dựng sẵn, trong bash lingo. (Có là một chức năng thư viện C chuẩn gọi là exit()
, và ngôn ngữ lập trình C có một từ dành riêng return
, nhưng những người không nên nhầm lẫn với các lệnh bash, mặc dù ngữ nghĩa của họ là tò mò tương tự.)
help <command>
vào shell của bạn để có được thông tin về những gì shellin sẽ làm. Trong trường hợp của bạnhelp return
vàhelp exit